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)
10 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
20 #include <mono/metadata/image.h>
21 #include <mono/metadata/assembly.h>
22 #include <mono/metadata/metadata.h>
23 #include <mono/metadata/metadata-internals.h>
24 #include <mono/metadata/profiler-private.h>
25 #include <mono/metadata/tabledefs.h>
26 #include <mono/metadata/tokentype.h>
27 #include <mono/metadata/class-internals.h>
28 #include <mono/metadata/object.h>
29 #include <mono/metadata/appdomain.h>
30 #include <mono/metadata/mono-endian.h>
31 #include <mono/metadata/debug-helpers.h>
32 #include <mono/metadata/reflection.h>
33 #include <mono/metadata/exception.h>
34 #include <mono/metadata/security-manager.h>
35 #include <mono/metadata/security-core-clr.h>
36 #include <mono/metadata/attrdefs.h>
37 #include <mono/metadata/gc-internals.h>
38 #include <mono/metadata/verify-internals.h>
39 #include <mono/metadata/mono-debug.h>
40 #include <mono/utils/mono-counters.h>
41 #include <mono/utils/mono-string.h>
42 #include <mono/utils/mono-error-internals.h>
43 #include <mono/utils/mono-logger-internals.h>
44 #include <mono/utils/mono-memory-model.h>
45 #include <mono/utils/atomic.h>
46 #include <mono/utils/bsearch.h>
47 #include <mono/utils/checked-build.h>
51 gboolean mono_print_vtable = FALSE;
52 gboolean mono_align_small_structs = FALSE;
55 guint32 inflated_classes, inflated_classes_size, inflated_methods_size;
56 guint32 classes_size, class_ext_size;
58 /* Low level lock which protects data structures in this module */
59 static mono_mutex_t classes_mutex;
61 /* Function supplied by the runtime to find classes by name using information from the AOT file */
62 static MonoGetClassFromName get_class_from_name = NULL;
64 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error);
65 static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
66 static gboolean can_access_type (MonoClass *access_klass, MonoClass *member_klass);
67 static MonoMethod* find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags);
68 static int generic_array_methods (MonoClass *klass);
69 static void setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos);
71 static MonoMethod* mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter);
72 static char* mono_assembly_name_from_token (MonoImage *image, guint32 type_token);
73 static void mono_field_resolve_type (MonoClassField *field, MonoError *error);
74 static guint32 mono_field_resolve_flags (MonoClassField *field);
75 static void mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup);
76 static void mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gklass);
79 We use gclass recording to allow recursive system f types to be referenced by a parent.
81 Given the following type hierarchy:
83 class TextBox : TextBoxBase<TextBox> {}
84 class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
85 class TextInput<T> : Input<T> where T: TextInput<T> {}
88 The runtime tries to load TextBoxBase<>.
89 To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
90 To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
91 To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
93 At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded
94 at this point, iow, both are registered in the type map and both and a NULL parent. This means
95 that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
97 To fix that what we do is to record all generic instantes created while resolving the parent of
98 any generic type definition and, after resolved, correct the parent field if needed.
101 static int record_gclass_instantiation;
102 static GSList *gclass_recorded_list;
103 typedef gboolean (*gclass_record_func) (MonoClass*, void*);
108 mono_locks_os_acquire (&classes_mutex, ClassesLock);
112 classes_unlock (void)
114 mono_locks_os_release (&classes_mutex, ClassesLock);
118 * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
121 enable_gclass_recording (void)
123 ++record_gclass_instantiation;
127 * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
130 disable_gclass_recording (gclass_record_func func, void *user_data)
132 GSList **head = &gclass_recorded_list;
134 g_assert (record_gclass_instantiation > 0);
135 --record_gclass_instantiation;
138 GSList *node = *head;
139 if (func ((MonoClass*)node->data, user_data)) {
141 g_slist_free_1 (node);
147 /* We automatically discard all recorded gclasses when disabled. */
148 if (!record_gclass_instantiation && gclass_recorded_list) {
149 g_slist_free (gclass_recorded_list);
150 gclass_recorded_list = NULL;
155 * mono_class_from_typeref:
156 * @image: a MonoImage
157 * @type_token: a TypeRef token
159 * Creates the MonoClass* structure representing the type defined by
160 * the typeref token valid inside @image.
161 * Returns: The MonoClass* representing the typeref token, NULL ifcould
165 mono_class_from_typeref (MonoImage *image, guint32 type_token)
168 MonoClass *klass = mono_class_from_typeref_checked (image, type_token, &error);
169 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
174 * mono_class_from_typeref_checked:
175 * @image: a MonoImage
176 * @type_token: a TypeRef token
177 * @error: error return code, if any.
179 * Creates the MonoClass* structure representing the type defined by
180 * the typeref token valid inside @image.
182 * Returns: The MonoClass* representing the typeref token, NULL if it could
183 * not be loaded with the @error value filled with the information about the
187 mono_class_from_typeref_checked (MonoImage *image, guint32 type_token, MonoError *error)
189 guint32 cols [MONO_TYPEREF_SIZE];
190 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
192 const char *name, *nspace;
193 MonoClass *res = NULL;
196 mono_error_init (error);
198 if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, error))
201 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
203 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
204 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
206 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
207 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
208 case MONO_RESOLUTION_SCOPE_MODULE:
210 LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
211 This is not the observed behavior of existing implementations.
212 The defacto behavior is that it's just a typedef in disguise.
214 /* a typedef in disguise */
215 res = mono_class_from_name_checked (image, nspace, name, error);
218 case MONO_RESOLUTION_SCOPE_MODULEREF:
219 module = mono_image_load_module (image, idx);
221 res = mono_class_from_name_checked (module, nspace, name, error);
224 case MONO_RESOLUTION_SCOPE_TYPEREF: {
225 MonoClass *enclosing;
228 if (idx == mono_metadata_token_index (type_token)) {
229 mono_error_set_bad_image (error, image, "Image with self-referencing typeref token %08x.", type_token);
233 enclosing = mono_class_from_typeref_checked (image, MONO_TOKEN_TYPE_REF | idx, error);
234 return_val_if_nok (error, NULL);
236 if (enclosing->nested_classes_inited && enclosing->ext) {
237 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
238 for (tmp = enclosing->ext->nested_classes; tmp; tmp = tmp->next) {
239 res = (MonoClass *)tmp->data;
240 if (strcmp (res->name, name) == 0)
244 /* Don't call mono_class_init as we might've been called by it recursively */
245 int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
247 guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
248 guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
249 const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
251 if (strcmp (nname, name) == 0)
252 return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, error);
254 i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
257 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name);
260 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
264 if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) {
265 mono_error_set_bad_image (error, image, "Image with invalid assemblyref token %08x.", idx);
269 if (!image->references || !image->references [idx - 1])
270 mono_assembly_load_reference (image, idx - 1);
271 g_assert (image->references [idx - 1]);
273 /* If the assembly did not load, register this as a type load exception */
274 if (image->references [idx - 1] == REFERENCE_MISSING){
275 MonoAssemblyName aname;
278 mono_assembly_get_assemblyref (image, idx - 1, &aname);
279 human_name = mono_stringify_assembly_name (&aname);
280 mono_error_set_assembly_load_simple (error, human_name, image->assembly ? image->assembly->ref_only : FALSE);
284 res = mono_class_from_name_checked (image->references [idx - 1]->image, nspace, name, error);
287 /* Generic case, should be avoided for when a better error is possible. */
288 if (!res && mono_error_ok (error)) {
289 if (mono_loader_get_last_error ()) { /*FIXME plug the above to not leak errors*/
290 mono_error_set_from_loader_error (error);
292 char *name = mono_class_name_from_token (image, type_token);
293 char *assembly = mono_assembly_name_from_token (image, type_token);
294 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
297 mono_loader_assert_no_error ();
303 mono_image_memdup (MonoImage *image, void *data, guint size)
305 void *res = mono_image_alloc (image, size);
306 memcpy (res, data, size);
310 /* Copy everything mono_metadata_free_array free. */
312 mono_dup_array_type (MonoImage *image, MonoArrayType *a)
315 a = (MonoArrayType *)mono_image_memdup (image, a, sizeof (MonoArrayType));
317 a->sizes = (int *)mono_image_memdup (image, a->sizes, a->numsizes * sizeof (int));
319 a->lobounds = (int *)mono_image_memdup (image, a->lobounds, a->numlobounds * sizeof (int));
321 a = (MonoArrayType *)g_memdup (a, sizeof (MonoArrayType));
323 a->sizes = (int *)g_memdup (a->sizes, a->numsizes * sizeof (int));
325 a->lobounds = (int *)g_memdup (a->lobounds, a->numlobounds * sizeof (int));
330 /* Copy everything mono_metadata_free_method_signature free. */
332 mono_metadata_signature_deep_dup (MonoImage *image, MonoMethodSignature *sig)
336 sig = mono_metadata_signature_dup_full (image, sig);
338 sig->ret = mono_metadata_type_dup (image, sig->ret);
339 for (i = 0; i < sig->param_count; ++i)
340 sig->params [i] = mono_metadata_type_dup (image, sig->params [i]);
346 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
348 MonoAssembly *ta = klass->image->assembly;
351 name = mono_stringify_assembly_name (&ta->aname);
352 g_string_append_printf (str, ", %s", name);
357 mono_type_name_check_byref (MonoType *type, GString *str)
360 g_string_append_c (str, '&');
364 * mono_identifier_escape_type_name_chars:
365 * @str: a destination string
366 * @identifier: an IDENTIFIER in internal form
370 * The displayed form of the identifier is appended to str.
372 * The displayed form of an identifier has the characters ,+&*[]\
373 * that have special meaning in type names escaped with a preceeding
374 * backslash (\) character.
377 mono_identifier_escape_type_name_chars (GString* str, const char* identifier)
383 // reserve space for common case: there will be no escaped characters.
384 g_string_set_size(str, n + strlen(identifier));
385 g_string_set_size(str, n);
387 for (const char* s = identifier; *s != 0 ; s++) {
396 g_string_append_c (str, '\\');
397 g_string_append_c (str, *s);
400 g_string_append_c (str, *s);
408 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
409 MonoTypeNameFormat format)
413 switch (type->type) {
414 case MONO_TYPE_ARRAY: {
415 int i, rank = type->data.array->rank;
416 MonoTypeNameFormat nested_format;
418 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
419 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
421 mono_type_get_name_recurse (
422 &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
423 g_string_append_c (str, '[');
425 g_string_append_c (str, '*');
426 for (i = 1; i < rank; i++)
427 g_string_append_c (str, ',');
428 g_string_append_c (str, ']');
430 mono_type_name_check_byref (type, str);
432 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
433 _mono_type_get_assembly_name (type->data.array->eklass, str);
436 case MONO_TYPE_SZARRAY: {
437 MonoTypeNameFormat nested_format;
439 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
440 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
442 mono_type_get_name_recurse (
443 &type->data.klass->byval_arg, str, FALSE, nested_format);
444 g_string_append (str, "[]");
446 mono_type_name_check_byref (type, str);
448 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
449 _mono_type_get_assembly_name (type->data.klass, str);
452 case MONO_TYPE_PTR: {
453 MonoTypeNameFormat nested_format;
455 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
456 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
458 mono_type_get_name_recurse (
459 type->data.type, str, FALSE, nested_format);
460 g_string_append_c (str, '*');
462 mono_type_name_check_byref (type, str);
464 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
465 _mono_type_get_assembly_name (mono_class_from_mono_type (type->data.type), str);
470 if (!mono_generic_param_info (type->data.generic_param))
471 g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num);
473 g_string_append (str, mono_generic_param_info (type->data.generic_param)->name);
475 mono_type_name_check_byref (type, str);
479 klass = mono_class_from_mono_type (type);
480 if (klass->nested_in) {
481 mono_type_get_name_recurse (
482 &klass->nested_in->byval_arg, str, TRUE, format);
483 if (format == MONO_TYPE_NAME_FORMAT_IL)
484 g_string_append_c (str, '.');
486 g_string_append_c (str, '+');
487 } else if (*klass->name_space) {
488 if (format == MONO_TYPE_NAME_FORMAT_IL)
489 g_string_append (str, klass->name_space);
491 mono_identifier_escape_type_name_chars (str, klass->name_space);
492 g_string_append_c (str, '.');
494 if (format == MONO_TYPE_NAME_FORMAT_IL) {
495 char *s = strchr (klass->name, '`');
496 int len = s ? s - klass->name : strlen (klass->name);
497 g_string_append_len (str, klass->name, len);
499 mono_identifier_escape_type_name_chars (str, klass->name);
503 if (klass->generic_class) {
504 MonoGenericClass *gclass = klass->generic_class;
505 MonoGenericInst *inst = gclass->context.class_inst;
506 MonoTypeNameFormat nested_format;
509 nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
510 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
512 if (format == MONO_TYPE_NAME_FORMAT_IL)
513 g_string_append_c (str, '<');
515 g_string_append_c (str, '[');
516 for (i = 0; i < inst->type_argc; i++) {
517 MonoType *t = inst->type_argv [i];
520 g_string_append_c (str, ',');
521 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
522 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
523 g_string_append_c (str, '[');
524 mono_type_get_name_recurse (inst->type_argv [i], str, FALSE, nested_format);
525 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
526 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
527 g_string_append_c (str, ']');
529 if (format == MONO_TYPE_NAME_FORMAT_IL)
530 g_string_append_c (str, '>');
532 g_string_append_c (str, ']');
533 } else if (klass->generic_container &&
534 (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
535 (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
538 if (format == MONO_TYPE_NAME_FORMAT_IL)
539 g_string_append_c (str, '<');
541 g_string_append_c (str, '[');
542 for (i = 0; i < klass->generic_container->type_argc; i++) {
544 g_string_append_c (str, ',');
545 g_string_append (str, mono_generic_container_get_param_info (klass->generic_container, i)->name);
547 if (format == MONO_TYPE_NAME_FORMAT_IL)
548 g_string_append_c (str, '>');
550 g_string_append_c (str, ']');
553 mono_type_name_check_byref (type, str);
555 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
556 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
557 _mono_type_get_assembly_name (klass, str);
563 * mono_type_get_name_full:
565 * @format: the format for the return string.
568 * Returns: The string representation in a number of formats:
570 * if format is MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
571 * returned in the formatrequired by System.Reflection, this is the
572 * inverse of mono_reflection_parse_type ().
574 * if format is MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
575 * be used by the IL assembler.
577 * if format is MONO_TYPE_NAME_FORMAT_FULL_NAME
579 * if format is MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
582 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
586 result = g_string_new ("");
588 mono_type_get_name_recurse (type, result, FALSE, format);
590 return g_string_free (result, FALSE);
594 * mono_type_get_full_name:
597 * Returns: The string representation for type as required by System.Reflection.
598 * The inverse of mono_reflection_parse_type ().
601 mono_type_get_full_name (MonoClass *klass)
603 return mono_type_get_name_full (mono_class_get_type (klass), MONO_TYPE_NAME_FORMAT_REFLECTION);
607 * mono_type_get_name:
610 * Returns: The string representation for type as it would be represented in IL code.
613 mono_type_get_name (MonoType *type)
615 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
619 * mono_type_get_underlying_type:
622 * Returns: The MonoType for the underlying integer type if @type
623 * is an enum and byref is false, otherwise the type itself.
626 mono_type_get_underlying_type (MonoType *type)
628 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype && !type->byref)
629 return mono_class_enum_basetype (type->data.klass);
630 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype && !type->byref)
631 return mono_class_enum_basetype (type->data.generic_class->container_class);
636 * mono_class_is_open_constructed_type:
639 * Returns: TRUE if type represents a generics open constructed type.
640 * IOW, not all type parameters required for the instantiation have
641 * been provided or it's a generic type definition.
643 * An open constructed type means it's a non realizable type. Not to
644 * be mixed up with an abstract type - we can't cast or dispatch to
645 * an open type, for example.
648 mono_class_is_open_constructed_type (MonoType *t)
654 case MONO_TYPE_SZARRAY:
655 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
656 case MONO_TYPE_ARRAY:
657 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
659 return mono_class_is_open_constructed_type (t->data.type);
660 case MONO_TYPE_GENERICINST:
661 return t->data.generic_class->context.class_inst->is_open;
662 case MONO_TYPE_CLASS:
663 case MONO_TYPE_VALUETYPE:
664 return t->data.klass->generic_container != NULL;
671 This is a simple function to catch the most common bad instances of generic types.
672 Specially those that might lead to further failures in the runtime.
675 is_valid_generic_argument (MonoType *type)
677 switch (type->type) {
679 //case MONO_TYPE_TYPEDBYREF:
687 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
689 mono_error_init (error);
691 switch (type->type) {
692 case MONO_TYPE_MVAR: {
694 int num = mono_type_get_generic_param_num (type);
695 MonoGenericInst *inst = context->method_inst;
698 if (num >= inst->type_argc) {
699 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
700 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
701 num, info ? info->name : "", inst->type_argc);
705 if (!is_valid_generic_argument (inst->type_argv [num])) {
706 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
707 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
708 num, info ? info->name : "", inst->type_argv [num]->type);
712 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
713 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
714 * ->byref and ->attrs from @type are propagated to the returned type.
716 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
717 nt->byref = type->byref;
718 nt->attrs = type->attrs;
721 case MONO_TYPE_VAR: {
723 int num = mono_type_get_generic_param_num (type);
724 MonoGenericInst *inst = context->class_inst;
727 if (num >= inst->type_argc) {
728 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
729 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
730 num, info ? info->name : "", inst->type_argc);
733 if (!is_valid_generic_argument (inst->type_argv [num])) {
734 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
735 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
736 num, info ? info->name : "", inst->type_argv [num]->type);
739 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
740 nt->byref = type->byref;
741 nt->attrs = type->attrs;
744 case MONO_TYPE_SZARRAY: {
745 MonoClass *eclass = type->data.klass;
746 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
747 if (!inflated || !mono_error_ok (error))
749 nt = mono_metadata_type_dup (image, type);
750 nt->data.klass = mono_class_from_mono_type (inflated);
751 mono_metadata_free_type (inflated);
754 case MONO_TYPE_ARRAY: {
755 MonoClass *eclass = type->data.array->eklass;
756 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
757 if (!inflated || !mono_error_ok (error))
759 nt = mono_metadata_type_dup (image, type);
760 nt->data.array->eklass = mono_class_from_mono_type (inflated);
761 mono_metadata_free_type (inflated);
764 case MONO_TYPE_GENERICINST: {
765 MonoGenericClass *gclass = type->data.generic_class;
766 MonoGenericInst *inst;
768 if (!gclass->context.class_inst->is_open)
771 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
772 return_val_if_nok (error, NULL);
774 if (inst != gclass->context.class_inst)
775 gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
777 if (gclass == type->data.generic_class)
780 nt = mono_metadata_type_dup (image, type);
781 nt->data.generic_class = gclass;
784 case MONO_TYPE_CLASS:
785 case MONO_TYPE_VALUETYPE: {
786 MonoClass *klass = type->data.klass;
787 MonoGenericContainer *container = klass->generic_container;
788 MonoGenericInst *inst;
789 MonoGenericClass *gclass = NULL;
795 /* We can't use context->class_inst directly, since it can have more elements */
796 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
797 return_val_if_nok (error, NULL);
799 if (inst == container->context.class_inst)
802 gclass = mono_metadata_lookup_generic_class (klass, inst, image_is_dynamic (klass->image));
804 nt = mono_metadata_type_dup (image, type);
805 nt->type = MONO_TYPE_GENERICINST;
806 nt->data.generic_class = gclass;
816 mono_generic_class_get_context (MonoGenericClass *gclass)
818 return &gclass->context;
822 mono_class_get_context (MonoClass *klass)
824 return klass->generic_class ? mono_generic_class_get_context (klass->generic_class) : NULL;
828 * mono_class_get_generic_container:
830 * Return the generic container of KLASS which should be a generic type definition.
832 MonoGenericContainer*
833 mono_class_get_generic_container (MonoClass *klass)
835 g_assert (klass->is_generic);
837 return klass->generic_container;
841 * mono_class_get_generic_class:
843 * Return the MonoGenericClass of KLASS, which should be a generic instance.
846 mono_class_get_generic_class (MonoClass *klass)
848 g_assert (klass->is_inflated);
850 return klass->generic_class;
854 * mono_class_inflate_generic_type_with_mempool:
855 * @mempool: a mempool
857 * @context: a generics context
858 * @error: error context
860 * The same as mono_class_inflate_generic_type, but allocates the MonoType
861 * from mempool if it is non-NULL. If it is NULL, the MonoType is
862 * allocated on the heap and is owned by the caller.
863 * The returned type can potentially be the same as TYPE, so it should not be
864 * modified by the caller, and it should be freed using mono_metadata_free_type ().
867 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
869 MonoType *inflated = NULL;
870 mono_error_init (error);
873 inflated = inflate_generic_type (image, type, context, error);
874 return_val_if_nok (error, NULL);
877 MonoType *shared = mono_metadata_get_shared_type (type);
882 return mono_metadata_type_dup (image, type);
886 mono_stats.inflated_type_count++;
891 * mono_class_inflate_generic_type:
893 * @context: a generics context
895 * If @type is a generic type and @context is not NULL, instantiate it using the
896 * generics context @context.
898 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
899 * on the heap and is owned by the caller. Returns NULL on error.
901 * @deprecated Please use mono_class_inflate_generic_type_checked instead
904 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
908 result = mono_class_inflate_generic_type_checked (type, context, &error);
909 mono_error_cleanup (&error);
914 * mono_class_inflate_generic_type:
916 * @context: a generics context
917 * @error: error context to use
919 * If @type is a generic type and @context is not NULL, instantiate it using the
920 * generics context @context.
922 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
923 * on the heap and is owned by the caller.
926 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
928 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
932 * mono_class_inflate_generic_type_no_copy:
934 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
938 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
940 MonoType *inflated = NULL;
942 mono_error_init (error);
944 inflated = inflate_generic_type (image, type, context, error);
945 return_val_if_nok (error, NULL);
951 mono_stats.inflated_type_count++;
956 * mono_class_inflate_generic_class:
958 * Inflate the class @gklass with @context. Set @error on failure.
961 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
966 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
967 return_val_if_nok (error, NULL);
969 res = mono_class_from_mono_type (inflated);
970 mono_metadata_free_type (inflated);
975 static MonoGenericContext
976 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
978 MonoGenericInst *class_inst = NULL;
979 MonoGenericInst *method_inst = NULL;
980 MonoGenericContext res = { NULL, NULL };
982 mono_error_init (error);
984 if (context->class_inst) {
985 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
986 if (!mono_error_ok (error))
990 if (context->method_inst) {
991 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
992 if (!mono_error_ok (error))
996 res.class_inst = class_inst;
997 res.method_inst = method_inst;
1003 * mono_class_inflate_generic_method:
1004 * @method: a generic method
1005 * @context: a generics context
1007 * Instantiate the generic method @method using the generics context @context.
1009 * Returns: The new instantiated method
1012 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
1014 return mono_class_inflate_generic_method_full (method, NULL, context);
1018 mono_class_inflate_generic_method_checked (MonoMethod *method, MonoGenericContext *context, MonoError *error)
1020 return mono_class_inflate_generic_method_full_checked (method, NULL, context, error);
1024 * mono_class_inflate_generic_method_full:
1026 * Instantiate method @method with the generic context @context.
1027 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
1028 * Use mono_method_signature () and mono_method_get_header () to get the correct values.
1031 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
1034 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
1035 if (!mono_error_ok (&error))
1036 /*FIXME do proper error handling - on this case, kill this function. */
1037 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
1043 * mono_class_inflate_generic_method_full_checked:
1044 * Same as mono_class_inflate_generic_method_full but return failure using @error.
1047 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
1050 MonoMethodInflated *iresult, *cached;
1051 MonoMethodSignature *sig;
1052 MonoGenericContext tmp_context;
1054 mono_error_init (error);
1056 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1057 while (method->is_inflated) {
1058 MonoGenericContext *method_context = mono_method_get_context (method);
1059 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1061 tmp_context = inflate_generic_context (method_context, context, error);
1062 return_val_if_nok (error, NULL);
1064 context = &tmp_context;
1066 if (mono_metadata_generic_context_equal (method_context, context))
1069 method = imethod->declaring;
1073 * A method only needs to be inflated if the context has argument for which it is
1076 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1077 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1080 if (!((method->is_generic && context->method_inst) ||
1081 (method->klass->generic_container && context->class_inst)))
1084 iresult = g_new0 (MonoMethodInflated, 1);
1085 iresult->context = *context;
1086 iresult->declaring = method;
1088 if (!context->method_inst && method->is_generic)
1089 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1091 if (!context->class_inst) {
1092 g_assert (!iresult->declaring->klass->generic_class);
1093 if (iresult->declaring->klass->generic_container)
1094 iresult->context.class_inst = iresult->declaring->klass->generic_container->context.class_inst;
1095 else if (iresult->declaring->klass->generic_class)
1096 iresult->context.class_inst = iresult->declaring->klass->generic_class->context.class_inst;
1098 /* This can happen with some callers like mono_object_get_virtual_method () */
1099 if (!iresult->declaring->klass->generic_container && !iresult->declaring->klass->generic_class)
1100 iresult->context.class_inst = NULL;
1102 MonoImageSet *set = mono_metadata_get_image_set_for_method (iresult);
1105 mono_image_set_lock (set);
1106 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1107 mono_image_set_unlock (set);
1111 return (MonoMethod*)cached;
1114 mono_stats.inflated_method_count++;
1116 inflated_methods_size += sizeof (MonoMethodInflated);
1118 sig = mono_method_signature (method);
1120 char *name = mono_type_get_full_name (method->klass);
1121 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1127 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1129 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1132 result = (MonoMethod *) iresult;
1133 result->is_inflated = TRUE;
1134 result->is_generic = FALSE;
1135 result->sre_method = FALSE;
1136 result->signature = NULL;
1138 if (!context->method_inst) {
1139 /* Set the generic_container of the result to the generic_container of method */
1140 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1142 if (generic_container) {
1143 result->is_generic = 1;
1144 mono_method_set_generic_container (result, generic_container);
1148 if (!klass_hint || !klass_hint->generic_class ||
1149 klass_hint->generic_class->container_class != method->klass ||
1150 klass_hint->generic_class->context.class_inst != context->class_inst)
1153 if (method->klass->generic_container)
1154 result->klass = klass_hint;
1156 if (!result->klass) {
1157 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1158 if (!mono_error_ok (error))
1161 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1163 mono_metadata_free_type (inflated);
1167 * FIXME: This should hold, but it doesn't:
1169 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1170 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1171 * g_assert (result->is_generic);
1174 * Fixing this here causes other things to break, hence a very
1175 * ugly hack in mini-trampolines.c - see
1176 * is_generic_method_definition().
1180 mono_image_set_lock (set);
1181 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1183 g_hash_table_insert (set->gmethod_cache, iresult, iresult);
1184 iresult->owner = set;
1187 mono_image_set_unlock (set);
1189 return (MonoMethod*)cached;
1197 * mono_get_inflated_method:
1199 * Obsolete. We keep it around since it's mentioned in the public API.
1202 mono_get_inflated_method (MonoMethod *method)
1208 * mono_method_get_context_general:
1210 * @uninflated: handle uninflated methods?
1212 * Returns the generic context of a method or NULL if it doesn't have
1213 * one. For an inflated method that's the context stored in the
1214 * method. Otherwise it's in the method's generic container or in the
1215 * generic container of the method's class.
1218 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1220 if (method->is_inflated) {
1221 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1222 return &imethod->context;
1226 if (method->is_generic)
1227 return &(mono_method_get_generic_container (method)->context);
1228 if (method->klass->generic_container)
1229 return &method->klass->generic_container->context;
1234 * mono_method_get_context:
1237 * Returns the generic context for method if it's inflated, otherwise
1241 mono_method_get_context (MonoMethod *method)
1243 return mono_method_get_context_general (method, FALSE);
1247 * mono_method_get_generic_container:
1249 * Returns the generic container of METHOD, which should be a generic method definition.
1250 * Returns NULL if METHOD is not a generic method definition.
1251 * LOCKING: Acquires the loader lock.
1253 MonoGenericContainer*
1254 mono_method_get_generic_container (MonoMethod *method)
1256 MonoGenericContainer *container;
1258 if (!method->is_generic)
1261 container = (MonoGenericContainer *)mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1262 g_assert (container);
1268 * mono_method_set_generic_container:
1270 * Sets the generic container of METHOD to CONTAINER.
1271 * LOCKING: Acquires the image lock.
1274 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1276 g_assert (method->is_generic);
1278 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1282 * mono_class_find_enum_basetype:
1283 * @class: The enum class
1285 * Determine the basetype of an enum by iterating through its fields. We do this
1286 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1289 mono_class_find_enum_basetype (MonoClass *klass, MonoError *error)
1291 MonoGenericContainer *container = NULL;
1292 MonoImage *m = klass->image;
1293 const int top = klass->field.count;
1296 g_assert (klass->enumtype);
1298 mono_error_init (error);
1300 if (klass->generic_container)
1301 container = klass->generic_container;
1302 else if (klass->generic_class) {
1303 MonoClass *gklass = klass->generic_class->container_class;
1305 container = gklass->generic_container;
1306 g_assert (container);
1310 * Fetch all the field information.
1312 for (i = 0; i < top; i++){
1314 guint32 cols [MONO_FIELD_SIZE];
1315 int idx = klass->field.first + i;
1318 /* klass->field.first and idx points into the fieldptr table */
1319 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1321 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1324 if (!mono_verifier_verify_field_signature (klass->image, cols [MONO_FIELD_SIGNATURE], NULL)) {
1325 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x", cols [MONO_FIELD_SIGNATURE]);
1329 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1330 mono_metadata_decode_value (sig, &sig);
1331 /* FIELD signature == 0x06 */
1333 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig);
1337 ftype = mono_metadata_parse_type_checked (m, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
1341 if (klass->generic_class) {
1342 //FIXME do we leak here?
1343 ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (klass), error);
1344 if (!mono_error_ok (error))
1346 ftype->attrs = cols [MONO_FIELD_FLAGS];
1351 mono_error_set_type_load_class (error, klass, "Could not find base type");
1354 mono_loader_assert_no_error ();
1359 * Checks for MonoClass::exception_type without resolving all MonoType's into MonoClass'es
1362 mono_type_has_exceptions (MonoType *type)
1364 switch (type->type) {
1365 case MONO_TYPE_CLASS:
1366 case MONO_TYPE_VALUETYPE:
1367 case MONO_TYPE_SZARRAY:
1368 return mono_class_has_failure (type->data.klass);
1369 case MONO_TYPE_ARRAY:
1370 return mono_class_has_failure (type->data.array->eklass);
1371 case MONO_TYPE_GENERICINST:
1372 return mono_class_has_failure (mono_generic_class_get_class (type->data.generic_class));
1381 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1385 mono_class_alloc (MonoClass *klass, int size)
1387 if (klass->generic_class)
1388 return mono_image_set_alloc (klass->generic_class->owner, size);
1390 return mono_image_alloc (klass->image, size);
1394 mono_class_alloc0 (MonoClass *klass, int size)
1398 res = mono_class_alloc (klass, size);
1399 memset (res, 0, size);
1403 #define mono_class_new0(klass,struct_type, n_structs) \
1404 ((struct_type *) mono_class_alloc0 ((klass), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1407 * mono_class_setup_basic_field_info:
1408 * @class: The class to initialize
1410 * Initializes the klass->fields.
1411 * LOCKING: Assumes the loader lock is held.
1414 mono_class_setup_basic_field_info (MonoClass *klass)
1416 MonoClassField *field;
1424 gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
1425 image = klass->image;
1426 top = klass->field.count;
1428 if (klass->generic_class && image_is_dynamic (klass->generic_class->container_class->image) && !klass->generic_class->container_class->wastypebuilder) {
1430 * This happens when a generic instance of an unfinished generic typebuilder
1431 * is used as an element type for creating an array type. We can't initialize
1432 * the fields of this class using the fields of gklass, since gklass is not
1433 * finished yet, fields could be added to it later.
1439 mono_class_setup_basic_field_info (gtd);
1441 top = gtd->field.count;
1442 klass->field.first = gtd->field.first;
1443 klass->field.count = gtd->field.count;
1446 klass->fields = (MonoClassField *)mono_class_alloc0 (klass, sizeof (MonoClassField) * top);
1449 * Fetch all the field information.
1451 for (i = 0; i < top; i++){
1452 field = &klass->fields [i];
1453 field->parent = klass;
1456 field->name = mono_field_get_name (>d->fields [i]);
1458 int idx = klass->field.first + i;
1459 /* klass->field.first and idx points into the fieldptr table */
1460 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1461 /* The name is needed for fieldrefs */
1462 field->name = mono_metadata_string_heap (image, name_idx);
1468 * mono_class_setup_fields:
1469 * @class: The class to initialize
1471 * Initializes the klass->fields.
1472 * LOCKING: Assumes the loader lock is held.
1475 mono_class_setup_fields (MonoClass *klass)
1478 MonoImage *m = klass->image;
1480 guint32 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1481 int i, blittable = TRUE;
1482 guint32 real_size = 0;
1483 guint32 packing_size = 0;
1485 gboolean explicit_size;
1486 MonoClassField *field;
1487 MonoGenericContainer *container = NULL;
1488 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
1491 * FIXME: We have a race condition here. It's possible that this function returns
1492 * to its caller with `instance_size` set to `0` instead of the actual size. This
1493 * is not a problem when the function is called recursively on the same class,
1494 * because the size will be initialized by the outer invocation. What follows is a
1495 * description of how it can occur in other cases, too. There it is a problem,
1496 * because it can lead to the GC being asked to allocate an object of size `0`,
1497 * which SGen chokes on. The race condition is triggered infrequently by
1498 * `tests/sgen-suspend.cs`.
1500 * This function is called for a class whenever one of its subclasses is inited.
1501 * For example, it's called for every subclass of Object. What it does is this:
1503 * if (klass->setup_fields_called)
1506 * klass->instance_size = 0;
1508 * klass->setup_fields_called = 1;
1509 * ... critical point
1510 * klass->instance_size = actual_instance_size;
1512 * The last two steps are sometimes reversed, but that only changes the way in which
1513 * the race condition works.
1515 * Assume thread A goes through this function and makes it to the critical point.
1516 * Now thread B runs the function and, since `setup_fields_called` is set, returns
1517 * immediately, but `instance_size` is incorrect.
1519 * The other case looks like this:
1521 * if (klass->setup_fields_called)
1523 * ... critical point X
1524 * klass->instance_size = 0;
1525 * ... critical point Y
1526 * klass->instance_size = actual_instance_size;
1528 * klass->setup_fields_called = 1;
1530 * Assume thread A goes through the function and makes it to critical point X. Now
1531 * thread B runs through the whole of the function, returning, assuming
1532 * `instance_size` is set. At that point thread A gets to run and makes it to
1533 * critical point Y, at which time `instance_size` is `0` again, invalidating thread
1536 if (klass->setup_fields_called)
1539 if (klass->generic_class && image_is_dynamic (klass->generic_class->container_class->image) && !klass->generic_class->container_class->wastypebuilder) {
1541 * This happens when a generic instance of an unfinished generic typebuilder
1542 * is used as an element type for creating an array type. We can't initialize
1543 * the fields of this class using the fields of gklass, since gklass is not
1544 * finished yet, fields could be added to it later.
1549 mono_class_setup_basic_field_info (klass);
1550 top = klass->field.count;
1553 mono_class_setup_fields (gtd);
1554 if (mono_class_has_failure (gtd)) {
1555 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1562 klass->sizes.class_size = 0;
1564 if (klass->parent) {
1565 /* For generic instances, klass->parent might not have been initialized */
1566 mono_class_init (klass->parent);
1567 if (!klass->parent->size_inited) {
1568 mono_class_setup_fields (klass->parent);
1569 if (mono_class_has_failure (klass->parent)) {
1570 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1574 instance_size += klass->parent->instance_size;
1575 klass->min_align = klass->parent->min_align;
1576 /* we use |= since it may have been set already */
1577 klass->has_references |= klass->parent->has_references;
1578 blittable = klass->parent->blittable;
1580 instance_size = sizeof (MonoObject);
1581 klass->min_align = 1;
1584 /* We can't really enable 16 bytes alignment until the GC supports it.
1585 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1586 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1587 Bug #506144 is an example of this issue.
1589 if (klass->simd_type)
1590 klass->min_align = 16;
1592 /* Get the real size */
1593 explicit_size = mono_metadata_packing_from_typedef (klass->image, klass->type_token, &packing_size, &real_size);
1595 if (explicit_size) {
1596 if ((packing_size & 0xffffff00) != 0) {
1597 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, packing_size);
1598 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
1601 klass->packing_size = packing_size;
1602 real_size += instance_size;
1606 if (explicit_size && real_size) {
1607 instance_size = MAX (real_size, instance_size);
1609 klass->blittable = blittable;
1610 if (!klass->instance_size)
1611 klass->instance_size = instance_size;
1612 mono_memory_barrier ();
1613 klass->size_inited = 1;
1614 klass->fields_inited = 1;
1615 klass->setup_fields_called = 1;
1619 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(mono_is_corlib_image (klass->image) && !strcmp (klass->name_space, "System") && !strcmp (klass->name, "ValueType")))
1622 /* Prevent infinite loops if the class references itself */
1623 klass->setup_fields_called = 1;
1625 if (klass->generic_container) {
1626 container = klass->generic_container;
1628 container = gtd->generic_container;
1629 g_assert (container);
1633 * Fetch all the field information.
1635 for (i = 0; i < top; i++){
1636 int idx = klass->field.first + i;
1637 field = &klass->fields [i];
1639 field->parent = klass;
1642 mono_field_resolve_type (field, &error);
1643 if (!mono_error_ok (&error)) {
1644 /*mono_field_resolve_type already failed class*/
1645 mono_error_cleanup (&error);
1649 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(klass), field->name);
1650 g_assert (field->type);
1653 if (mono_field_is_deleted (field))
1656 MonoClassField *gfield = >d->fields [i];
1657 field->offset = gfield->offset;
1659 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1661 mono_metadata_field_info (m, idx, &offset, NULL, NULL);
1662 field->offset = offset;
1664 if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1665 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Missing field layout info for %s", field->name));
1668 if (field->offset < -1) { /*-1 is used to encode special static fields */
1669 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Invalid negative field offset %d for %s", field->offset, field->name));
1672 if (klass->generic_container) {
1673 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic class cannot have explicit layout."));
1679 /* Only do these checks if we still think this type is blittable */
1680 if (blittable && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1681 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1684 MonoClass *field_class = mono_class_from_mono_type (field->type);
1686 mono_class_setup_fields (field_class);
1687 if (mono_class_has_failure (field_class)) {
1688 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1692 if (!field_class || !field_class->blittable)
1697 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1698 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
1699 blittable = klass->element_class->blittable;
1702 if (mono_type_has_exceptions (field->type)) {
1703 char *class_name = mono_type_get_full_name (klass);
1704 char *type_name = mono_type_full_name (field->type);
1706 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1707 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1708 g_free (class_name);
1712 /* The def_value of fields is compute lazily during vtable creation */
1715 if (klass == mono_defaults.string_class)
1718 klass->blittable = blittable;
1720 if (klass->enumtype && !mono_class_enum_basetype (klass)) {
1721 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1724 if (explicit_size && real_size) {
1725 instance_size = MAX (real_size, instance_size);
1728 if (mono_class_has_failure (klass))
1730 mono_class_layout_fields (klass, instance_size);
1732 /*valuetypes can't be neither bigger than 1Mb or empty. */
1733 if (klass->valuetype && (klass->instance_size <= 0 || klass->instance_size > (0x100000 + sizeof (MonoObject))))
1734 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1736 mono_memory_barrier ();
1737 klass->fields_inited = 1;
1741 * mono_class_setup_fields_locking:
1742 * @class: The class to initialize
1744 * Initializes the klass->fields array of fields.
1745 * Aquires the loader lock.
1748 mono_class_setup_fields_locking (MonoClass *klass)
1750 /* This can be checked without locks */
1751 if (klass->fields_inited)
1753 mono_loader_lock ();
1754 mono_class_setup_fields (klass);
1755 mono_loader_unlock ();
1759 * mono_class_has_references:
1761 * Returns whenever @klass->has_references is set, initializing it if needed.
1762 * Aquires the loader lock.
1765 mono_class_has_references (MonoClass *klass)
1767 if (klass->init_pending) {
1768 /* Be conservative */
1771 mono_class_init (klass);
1773 return klass->has_references;
1778 * mono_type_get_basic_type_from_generic:
1781 * Returns a closed type corresponding to the possibly open type
1785 mono_type_get_basic_type_from_generic (MonoType *type)
1787 /* When we do generic sharing we let type variables stand for reference/primitive types. */
1788 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) &&
1789 (!type->data.generic_param->gshared_constraint || type->data.generic_param->gshared_constraint->type == MONO_TYPE_OBJECT))
1790 return &mono_defaults.object_class->byval_arg;
1795 type_has_references (MonoClass *klass, MonoType *ftype)
1797 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)))))
1799 if (!ftype->byref && (ftype->type == MONO_TYPE_VAR || ftype->type == MONO_TYPE_MVAR)) {
1800 MonoGenericParam *gparam = ftype->data.generic_param;
1802 if (gparam->gshared_constraint)
1803 return mono_class_has_references (mono_class_from_mono_type (gparam->gshared_constraint));
1809 * mono_class_layout_fields:
1811 * @instance_size: base instance size
1813 * Compute the placement of fields inside an object or struct, according to
1814 * the layout rules and set the following fields in @class:
1815 * - has_references (if the class contains instance references firled or structs that contain references)
1816 * - has_static_refs (same, but for static fields)
1817 * - instance_size (size of the object in memory)
1818 * - class_size (size needed for the static fields)
1819 * - size_inited (flag set when the instance_size is set)
1821 * LOCKING: this is supposed to be called with the loader lock held.
1824 mono_class_layout_fields (MonoClass *klass, int instance_size)
1827 const int top = klass->field.count;
1828 guint32 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1829 guint32 pass, passes, real_size;
1830 gboolean gc_aware_layout = FALSE;
1831 gboolean has_static_fields = FALSE;
1832 MonoClassField *field;
1835 * When we do generic sharing we need to have layout
1836 * information for open generic classes (either with a generic
1837 * context containing type variables or with a generic
1838 * container), so we don't return in that case anymore.
1842 * Enable GC aware auto layout: in this mode, reference
1843 * fields are grouped together inside objects, increasing collector
1845 * Requires that all classes whose layout is known to native code be annotated
1846 * with [StructLayout (LayoutKind.Sequential)]
1847 * Value types have gc_aware_layout disabled by default, as per
1848 * what the default is for other runtimes.
1850 /* corlib is missing [StructLayout] directives in many places */
1851 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1852 if (!klass->valuetype)
1853 gc_aware_layout = TRUE;
1856 /* Compute klass->has_references */
1858 * Process non-static fields first, since static fields might recursively
1859 * refer to the class itself.
1861 for (i = 0; i < top; i++) {
1864 field = &klass->fields [i];
1866 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1867 ftype = mono_type_get_underlying_type (field->type);
1868 ftype = mono_type_get_basic_type_from_generic (ftype);
1869 if (type_has_references (klass, ftype))
1870 klass->has_references = TRUE;
1874 for (i = 0; i < top; i++) {
1877 field = &klass->fields [i];
1879 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1880 ftype = mono_type_get_underlying_type (field->type);
1881 ftype = mono_type_get_basic_type_from_generic (ftype);
1882 if (type_has_references (klass, ftype))
1883 klass->has_static_refs = TRUE;
1887 for (i = 0; i < top; i++) {
1890 field = &klass->fields [i];
1892 ftype = mono_type_get_underlying_type (field->type);
1893 ftype = mono_type_get_basic_type_from_generic (ftype);
1894 if (type_has_references (klass, ftype)) {
1895 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1896 klass->has_static_refs = TRUE;
1898 klass->has_references = TRUE;
1903 * Compute field layout and total size (not considering static fields)
1906 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1907 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1909 if (gc_aware_layout)
1914 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1917 if (klass->parent) {
1918 mono_class_setup_fields (klass->parent);
1919 if (mono_class_has_failure (klass->parent)) {
1920 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1923 real_size = klass->parent->instance_size;
1925 real_size = sizeof (MonoObject);
1928 for (pass = 0; pass < passes; ++pass) {
1929 for (i = 0; i < top; i++){
1934 field = &klass->fields [i];
1936 if (mono_field_is_deleted (field))
1938 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1941 ftype = mono_type_get_underlying_type (field->type);
1942 ftype = mono_type_get_basic_type_from_generic (ftype);
1943 if (gc_aware_layout) {
1944 if (type_has_references (klass, ftype)) {
1953 if ((top == 1) && (klass->instance_size == sizeof (MonoObject)) &&
1954 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1955 /* This field is a hack inserted by MCS to empty structures */
1959 size = mono_type_size (field->type, &align);
1961 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1962 align = klass->packing_size ? MIN (klass->packing_size, align): align;
1963 /* if the field has managed references, we need to force-align it
1966 if (type_has_references (klass, ftype))
1967 align = MAX (align, sizeof (gpointer));
1969 klass->min_align = MAX (align, klass->min_align);
1970 field->offset = real_size;
1972 field->offset += align - 1;
1973 field->offset &= ~(align - 1);
1975 /*TypeBuilders produce all sort of weird things*/
1976 g_assert (image_is_dynamic (klass->image) || field->offset > 0);
1977 real_size = field->offset + size;
1980 instance_size = MAX (real_size, instance_size);
1982 if (instance_size & (klass->min_align - 1)) {
1983 instance_size += klass->min_align - 1;
1984 instance_size &= ~(klass->min_align - 1);
1988 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
1992 for (i = 0; i < top; i++) {
1997 field = &klass->fields [i];
2000 * There must be info about all the fields in a type if it
2001 * uses explicit layout.
2003 if (mono_field_is_deleted (field))
2005 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2008 size = mono_type_size (field->type, &align);
2009 align = klass->packing_size ? MIN (klass->packing_size, align): align;
2010 klass->min_align = MAX (align, klass->min_align);
2013 * When we get here, field->offset is already set by the
2014 * loader (for either runtime fields or fields loaded from metadata).
2015 * The offset is from the start of the object: this works for both
2016 * classes and valuetypes.
2018 field->offset += sizeof (MonoObject);
2019 ftype = mono_type_get_underlying_type (field->type);
2020 ftype = mono_type_get_basic_type_from_generic (ftype);
2021 if (type_has_references (klass, ftype)) {
2022 if (field->offset % sizeof (gpointer)) {
2023 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
2030 real_size = MAX (real_size, size + field->offset);
2033 if (klass->has_references) {
2034 ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
2036 /* Check for overlapping reference and non-reference fields */
2037 for (i = 0; i < top; i++) {
2040 field = &klass->fields [i];
2042 if (mono_field_is_deleted (field))
2044 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2046 ftype = mono_type_get_underlying_type (field->type);
2047 if (MONO_TYPE_IS_REFERENCE (ftype))
2048 ref_bitmap [field->offset / sizeof (gpointer)] = 1;
2050 for (i = 0; i < top; i++) {
2051 field = &klass->fields [i];
2053 if (mono_field_is_deleted (field))
2055 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2058 // FIXME: Too much code does this
2060 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field->offset / sizeof (gpointer)]) {
2061 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);
2062 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
2066 g_free (ref_bitmap);
2069 instance_size = MAX (real_size, instance_size);
2070 if (instance_size & (klass->min_align - 1)) {
2071 instance_size += klass->min_align - 1;
2072 instance_size &= ~(klass->min_align - 1);
2078 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2080 * This leads to all kinds of problems with nested structs, so only
2081 * enable it when a MONO_DEBUG property is set.
2083 * For small structs, set min_align to at least the struct size to improve
2084 * performance, and since the JIT memset/memcpy code assumes this and generates
2085 * unaligned accesses otherwise. See #78990 for a testcase.
2087 if (mono_align_small_structs) {
2088 if (instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2089 klass->min_align = MAX (klass->min_align, instance_size - sizeof (MonoObject));
2093 if (klass->instance_size && !klass->image->dynamic) {
2094 /* Might be already set using cached info */
2095 g_assert (klass->instance_size == instance_size);
2097 klass->instance_size = instance_size;
2099 mono_memory_barrier ();
2100 klass->size_inited = 1;
2103 * Compute static field layout and size
2105 for (i = 0; i < top; i++){
2109 field = &klass->fields [i];
2111 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2113 if (mono_field_is_deleted (field))
2116 if (mono_type_has_exceptions (field->type)) {
2117 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
2121 has_static_fields = TRUE;
2123 size = mono_type_size (field->type, &align);
2124 field->offset = klass->sizes.class_size;
2125 /*align is always non-zero here*/
2126 field->offset += align - 1;
2127 field->offset &= ~(align - 1);
2128 klass->sizes.class_size = field->offset + size;
2131 if (has_static_fields && klass->sizes.class_size == 0)
2132 /* Simplify code which depends on class_size != 0 if the class has static fields */
2133 klass->sizes.class_size = 8;
2137 create_array_method (MonoClass *klass, const char *name, MonoMethodSignature *sig)
2141 method = (MonoMethod *) mono_image_alloc0 (klass->image, sizeof (MonoMethodPInvoke));
2142 method->klass = klass;
2143 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2144 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2145 method->signature = sig;
2146 method->name = name;
2149 if (name [0] == '.') {
2150 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2152 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2158 * mono_class_setup_methods:
2161 * Initializes the 'methods' array in CLASS.
2162 * Calling this method should be avoided if possible since it allocates a lot
2163 * of long-living MonoMethod structures.
2164 * Methods belonging to an interface are assigned a sequential slot starting
2167 * On failure this function sets klass->exception_type
2170 mono_class_setup_methods (MonoClass *klass)
2173 MonoMethod **methods;
2178 if (klass->generic_class) {
2180 MonoClass *gklass = klass->generic_class->container_class;
2182 mono_class_init (gklass);
2183 if (!mono_class_has_failure (gklass))
2184 mono_class_setup_methods (gklass);
2185 if (mono_class_has_failure (gklass)) {
2186 /* FIXME make exception_data less opaque so it's possible to dup it here */
2187 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2191 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2192 count = gklass->method.count;
2193 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * (count + 1));
2195 for (i = 0; i < count; i++) {
2196 methods [i] = mono_class_inflate_generic_method_full_checked (
2197 gklass->methods [i], klass, mono_class_get_context (klass), &error);
2198 if (!mono_error_ok (&error)) {
2199 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2200 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)));
2203 mono_error_cleanup (&error);
2207 } else if (klass->rank) {
2209 MonoMethod *amethod;
2210 MonoMethodSignature *sig;
2211 int count_generic = 0, first_generic = 0;
2213 gboolean jagged_ctor = FALSE;
2215 count = 3 + (klass->rank > 1? 2: 1);
2217 mono_class_setup_interfaces (klass, &error);
2218 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2220 if (klass->rank == 1 && klass->element_class->rank) {
2222 klass->method.count ++;
2225 if (klass->interface_count) {
2226 count_generic = generic_array_methods (klass);
2227 first_generic = count;
2228 count += klass->interface_count * count_generic;
2231 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * count);
2233 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2234 sig->ret = &mono_defaults.void_class->byval_arg;
2235 sig->pinvoke = TRUE;
2236 sig->hasthis = TRUE;
2237 for (i = 0; i < klass->rank; ++i)
2238 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2240 amethod = create_array_method (klass, ".ctor", sig);
2241 methods [method_num++] = amethod;
2242 if (klass->rank > 1) {
2243 sig = mono_metadata_signature_alloc (klass->image, klass->rank * 2);
2244 sig->ret = &mono_defaults.void_class->byval_arg;
2245 sig->pinvoke = TRUE;
2246 sig->hasthis = TRUE;
2247 for (i = 0; i < klass->rank * 2; ++i)
2248 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2250 amethod = create_array_method (klass, ".ctor", sig);
2251 methods [method_num++] = amethod;
2255 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2256 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2257 sig->ret = &mono_defaults.void_class->byval_arg;
2258 sig->pinvoke = TRUE;
2259 sig->hasthis = TRUE;
2260 for (i = 0; i < klass->rank + 1; ++i)
2261 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2262 amethod = create_array_method (klass, ".ctor", sig);
2263 methods [method_num++] = amethod;
2266 /* element Get (idx11, [idx2, ...]) */
2267 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2268 sig->ret = &klass->element_class->byval_arg;
2269 sig->pinvoke = TRUE;
2270 sig->hasthis = TRUE;
2271 for (i = 0; i < klass->rank; ++i)
2272 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2273 amethod = create_array_method (klass, "Get", sig);
2274 methods [method_num++] = amethod;
2275 /* element& Address (idx11, [idx2, ...]) */
2276 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2277 sig->ret = &klass->element_class->this_arg;
2278 sig->pinvoke = TRUE;
2279 sig->hasthis = TRUE;
2280 for (i = 0; i < klass->rank; ++i)
2281 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2282 amethod = create_array_method (klass, "Address", sig);
2283 methods [method_num++] = amethod;
2284 /* void Set (idx11, [idx2, ...], element) */
2285 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2286 sig->ret = &mono_defaults.void_class->byval_arg;
2287 sig->pinvoke = TRUE;
2288 sig->hasthis = TRUE;
2289 for (i = 0; i < klass->rank; ++i)
2290 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2291 sig->params [i] = &klass->element_class->byval_arg;
2292 amethod = create_array_method (klass, "Set", sig);
2293 methods [method_num++] = amethod;
2295 for (i = 0; i < klass->interface_count; i++)
2296 setup_generic_array_ifaces (klass, klass->interfaces [i], methods, first_generic + i * count_generic);
2300 count = klass->method.count;
2301 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * count);
2302 for (i = 0; i < count; ++i) {
2303 int idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_METHOD, klass->method.first + i + 1);
2304 methods [i] = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | idx, klass, NULL, &error);
2306 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)));
2307 mono_error_cleanup (&error);
2312 if (MONO_CLASS_IS_INTERFACE (klass)) {
2314 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2315 for (i = 0; i < count; ++i) {
2316 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2317 methods [i]->slot = slot++;
2321 mono_image_lock (klass->image);
2323 if (!klass->methods) {
2324 klass->method.count = count;
2326 /* Needed because of the double-checking locking pattern */
2327 mono_memory_barrier ();
2329 klass->methods = methods;
2332 mono_image_unlock (klass->image);
2336 * mono_class_get_method_by_index:
2338 * Returns klass->methods [index], initializing klass->methods if neccesary.
2340 * LOCKING: Acquires the loader lock.
2343 mono_class_get_method_by_index (MonoClass *klass, int index)
2346 /* Avoid calling setup_methods () if possible */
2347 if (klass->generic_class && !klass->methods) {
2348 MonoClass *gklass = klass->generic_class->container_class;
2351 m = mono_class_inflate_generic_method_full_checked (
2352 gklass->methods [index], klass, mono_class_get_context (klass), &error);
2353 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2355 * If setup_methods () is called later for this class, no duplicates are created,
2356 * since inflate_generic_method guarantees that only one instance of a method
2357 * is created for each context.
2360 mono_class_setup_methods (klass);
2361 g_assert (m == klass->methods [index]);
2365 mono_class_setup_methods (klass);
2366 if (mono_class_has_failure (klass)) /*FIXME do proper error handling*/
2368 g_assert (index >= 0 && index < klass->method.count);
2369 return klass->methods [index];
2374 * mono_class_get_inflated_method:
2376 * Given an inflated class CLASS and a method METHOD which should be a method of
2377 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2380 mono_class_get_inflated_method (MonoClass *klass, MonoMethod *method)
2382 MonoClass *gklass = klass->generic_class->container_class;
2385 g_assert (method->klass == gklass);
2387 mono_class_setup_methods (gklass);
2388 g_assert (!mono_class_has_failure (gklass)); /*FIXME do proper error handling*/
2390 for (i = 0; i < gklass->method.count; ++i) {
2391 if (gklass->methods [i] == method) {
2392 if (klass->methods) {
2393 return klass->methods [i];
2396 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], klass, mono_class_get_context (klass), &error);
2397 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2407 * mono_class_get_vtable_entry:
2409 * Returns klass->vtable [offset], computing it if neccesary. Returns NULL on failure.
2410 * LOCKING: Acquires the loader lock.
2413 mono_class_get_vtable_entry (MonoClass *klass, int offset)
2417 if (klass->rank == 1) {
2419 * szarrays do not overwrite any methods of Array, so we can avoid
2420 * initializing their vtables in some cases.
2422 mono_class_setup_vtable (klass->parent);
2423 if (offset < klass->parent->vtable_size)
2424 return klass->parent->vtable [offset];
2427 if (klass->generic_class) {
2429 MonoClass *gklass = klass->generic_class->container_class;
2430 mono_class_setup_vtable (gklass);
2431 m = gklass->vtable [offset];
2433 m = mono_class_inflate_generic_method_full_checked (m, klass, mono_class_get_context (klass), &error);
2434 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2436 mono_class_setup_vtable (klass);
2437 if (mono_class_has_failure (klass))
2439 m = klass->vtable [offset];
2446 * mono_class_get_vtable_size:
2448 * Return the vtable size for KLASS.
2451 mono_class_get_vtable_size (MonoClass *klass)
2453 mono_class_setup_vtable (klass);
2455 return klass->vtable_size;
2459 * mono_class_setup_properties:
2461 * Initialize klass->ext.property and klass->ext.properties.
2463 * This method can fail the class.
2466 mono_class_setup_properties (MonoClass *klass)
2468 guint startm, endm, i, j;
2469 guint32 cols [MONO_PROPERTY_SIZE];
2470 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2471 MonoProperty *properties;
2475 if (klass->ext && klass->ext->properties)
2478 if (klass->generic_class) {
2479 MonoClass *gklass = klass->generic_class->container_class;
2481 mono_class_init (gklass);
2482 mono_class_setup_properties (gklass);
2483 if (mono_class_has_failure (gklass)) {
2484 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2488 properties = mono_class_new0 (klass, MonoProperty, gklass->ext->property.count + 1);
2490 for (i = 0; i < gklass->ext->property.count; i++) {
2492 MonoProperty *prop = &properties [i];
2494 *prop = gklass->ext->properties [i];
2497 prop->get = mono_class_inflate_generic_method_full_checked (
2498 prop->get, klass, mono_class_get_context (klass), &error);
2500 prop->set = mono_class_inflate_generic_method_full_checked (
2501 prop->set, klass, mono_class_get_context (klass), &error);
2503 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2504 prop->parent = klass;
2507 first = gklass->ext->property.first;
2508 count = gklass->ext->property.count;
2510 first = mono_metadata_properties_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2511 count = last - first;
2514 mono_class_setup_methods (klass);
2515 if (mono_class_has_failure (klass))
2519 properties = (MonoProperty *)mono_class_alloc0 (klass, sizeof (MonoProperty) * count);
2520 for (i = first; i < last; ++i) {
2521 mono_metadata_decode_table_row (klass->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2522 properties [i - first].parent = klass;
2523 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2524 properties [i - first].name = mono_metadata_string_heap (klass->image, cols [MONO_PROPERTY_NAME]);
2526 startm = mono_metadata_methods_from_property (klass->image, i, &endm);
2527 for (j = startm; j < endm; ++j) {
2530 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2532 if (klass->image->uncompressed_metadata) {
2534 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2535 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2536 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2538 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - klass->method.first];
2541 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2542 case METHOD_SEMANTIC_SETTER:
2543 properties [i - first].set = method;
2545 case METHOD_SEMANTIC_GETTER:
2546 properties [i - first].get = method;
2555 mono_class_alloc_ext (klass);
2557 mono_image_lock (klass->image);
2559 if (klass->ext->properties) {
2560 /* We leak 'properties' which was allocated from the image mempool */
2561 mono_image_unlock (klass->image);
2565 klass->ext->property.first = first;
2566 klass->ext->property.count = count;
2568 /* Flush any pending writes as we do double checked locking on klass->ext->properties */
2569 mono_memory_barrier ();
2571 /* Leave this assignment as the last op in the function */
2572 klass->ext->properties = properties;
2574 mono_image_unlock (klass->image);
2578 inflate_method_listz (MonoMethod **methods, MonoClass *klass, MonoGenericContext *context)
2580 MonoMethod **om, **retval;
2583 for (om = methods, count = 0; *om; ++om, ++count)
2586 retval = g_new0 (MonoMethod*, count + 1);
2588 for (om = methods, count = 0; *om; ++om, ++count) {
2590 retval [count] = mono_class_inflate_generic_method_full_checked (*om, klass, context, &error);
2591 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2597 /*This method can fail the class.*/
2599 mono_class_setup_events (MonoClass *klass)
2602 guint startm, endm, i, j;
2603 guint32 cols [MONO_EVENT_SIZE];
2604 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2608 if (klass->ext && klass->ext->events)
2611 if (klass->generic_class) {
2612 MonoClass *gklass = klass->generic_class->container_class;
2613 MonoGenericContext *context = NULL;
2615 mono_class_setup_events (gklass);
2616 if (mono_class_has_failure (gklass)) {
2617 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2621 first = gklass->ext->event.first;
2622 count = gklass->ext->event.count;
2624 events = mono_class_new0 (klass, MonoEvent, count);
2627 context = mono_class_get_context (klass);
2629 for (i = 0; i < count; i++) {
2631 MonoEvent *event = &events [i];
2632 MonoEvent *gevent = &gklass->ext->events [i];
2634 mono_error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2636 event->parent = klass;
2637 event->name = gevent->name;
2638 event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, klass, context, &error) : NULL;
2639 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2640 event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, klass, context, &error) : NULL;
2641 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2642 event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, klass, context, &error) : NULL;
2643 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2645 #ifndef MONO_SMALL_CONFIG
2646 event->other = gevent->other ? inflate_method_listz (gevent->other, klass, context) : NULL;
2648 event->attrs = gevent->attrs;
2651 first = mono_metadata_events_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2652 count = last - first;
2655 mono_class_setup_methods (klass);
2656 if (mono_class_has_failure (klass)) {
2657 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2662 events = (MonoEvent *)mono_class_alloc0 (klass, sizeof (MonoEvent) * count);
2663 for (i = first; i < last; ++i) {
2664 MonoEvent *event = &events [i - first];
2666 mono_metadata_decode_table_row (klass->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2667 event->parent = klass;
2668 event->attrs = cols [MONO_EVENT_FLAGS];
2669 event->name = mono_metadata_string_heap (klass->image, cols [MONO_EVENT_NAME]);
2671 startm = mono_metadata_methods_from_event (klass->image, i, &endm);
2672 for (j = startm; j < endm; ++j) {
2675 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2677 if (klass->image->uncompressed_metadata) {
2679 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2680 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2681 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2683 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - klass->method.first];
2686 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2687 case METHOD_SEMANTIC_ADD_ON:
2688 event->add = method;
2690 case METHOD_SEMANTIC_REMOVE_ON:
2691 event->remove = method;
2693 case METHOD_SEMANTIC_FIRE:
2694 event->raise = method;
2696 case METHOD_SEMANTIC_OTHER: {
2697 #ifndef MONO_SMALL_CONFIG
2700 if (event->other == NULL) {
2701 event->other = g_new0 (MonoMethod*, 2);
2703 while (event->other [n])
2705 event->other = (MonoMethod **)g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2707 event->other [n] = method;
2708 /* NULL terminated */
2709 event->other [n + 1] = NULL;
2720 mono_class_alloc_ext (klass);
2722 mono_image_lock (klass->image);
2724 if (klass->ext->events) {
2725 mono_image_unlock (klass->image);
2729 klass->ext->event.first = first;
2730 klass->ext->event.count = count;
2732 /* Flush any pending writes as we do double checked locking on klass->ext.events */
2733 mono_memory_barrier ();
2735 /* Leave this assignment as the last op in the function */
2736 klass->ext->events = events;
2738 mono_image_unlock (klass->image);
2742 * Global pool of interface IDs, represented as a bitset.
2743 * LOCKING: Protected by the classes lock.
2745 static MonoBitSet *global_interface_bitset = NULL;
2748 * mono_unload_interface_ids:
2749 * @bitset: bit set of interface IDs
2751 * When an image is unloaded, the interface IDs associated with
2752 * the image are put back in the global pool of IDs so the numbers
2756 mono_unload_interface_ids (MonoBitSet *bitset)
2759 mono_bitset_sub (global_interface_bitset, bitset);
2764 mono_unload_interface_id (MonoClass *klass)
2766 if (global_interface_bitset && klass->interface_id) {
2768 mono_bitset_clear (global_interface_bitset, klass->interface_id);
2774 * mono_get_unique_iid:
2777 * Assign a unique integer ID to the interface represented by @class.
2778 * The ID will positive and as small as possible.
2779 * LOCKING: Acquires the classes lock.
2780 * Returns: The new ID.
2783 mono_get_unique_iid (MonoClass *klass)
2787 g_assert (MONO_CLASS_IS_INTERFACE (klass));
2791 if (!global_interface_bitset) {
2792 global_interface_bitset = mono_bitset_new (128, 0);
2795 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2797 int old_size = mono_bitset_size (global_interface_bitset);
2798 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2799 mono_bitset_free (global_interface_bitset);
2800 global_interface_bitset = new_set;
2803 mono_bitset_set (global_interface_bitset, iid);
2804 /* set the bit also in the per-image set */
2805 if (!klass->generic_class) {
2806 if (klass->image->interface_bitset) {
2807 if (iid >= mono_bitset_size (klass->image->interface_bitset)) {
2808 MonoBitSet *new_set = mono_bitset_clone (klass->image->interface_bitset, iid + 1);
2809 mono_bitset_free (klass->image->interface_bitset);
2810 klass->image->interface_bitset = new_set;
2813 klass->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2815 mono_bitset_set (klass->image->interface_bitset, iid);
2820 #ifndef MONO_SMALL_CONFIG
2821 if (mono_print_vtable) {
2823 char *type_name = mono_type_full_name (&klass->byval_arg);
2824 if (klass->generic_class && !klass->generic_class->context.class_inst->is_open) {
2825 generic_id = klass->generic_class->context.class_inst->id;
2826 g_assert (generic_id != 0);
2830 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, klass->image->name, type_name, generic_id);
2835 g_assert (iid <= 65535);
2840 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2845 mono_class_setup_interfaces (klass, error);
2846 return_if_nok (error);
2848 for (i = 0; i < klass->interface_count; i++) {
2849 ic = klass->interfaces [i];
2852 *res = g_ptr_array_new ();
2853 g_ptr_array_add (*res, ic);
2854 mono_class_init (ic);
2855 if (mono_class_has_failure (ic)) {
2856 mono_error_set_type_load_class (error, ic, "Error Loading class");
2860 collect_implemented_interfaces_aux (ic, res, error);
2861 return_if_nok (error);
2866 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2868 GPtrArray *res = NULL;
2870 collect_implemented_interfaces_aux (klass, &res, error);
2871 if (!mono_error_ok (error)) {
2873 g_ptr_array_free (res, TRUE);
2880 compare_interface_ids (const void *p_key, const void *p_element) {
2881 const MonoClass *key = (const MonoClass *)p_key;
2882 const MonoClass *element = *(const MonoClass **)p_element;
2884 return (key->interface_id - element->interface_id);
2887 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2889 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2890 MonoClass **result = (MonoClass **)mono_binary_search (
2892 klass->interfaces_packed,
2893 klass->interface_offsets_count,
2894 sizeof (MonoClass *),
2895 compare_interface_ids);
2897 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2904 * mono_class_interface_offset_with_variance:
2906 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2907 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2909 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2911 * FIXME figure out MS disambiguation rules and fix this function.
2914 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2915 int i = mono_class_interface_offset (klass, itf);
2916 *non_exact_match = FALSE;
2920 if (!mono_class_has_variant_generic_params (itf))
2923 for (i = 0; i < klass->interface_offsets_count; i++) {
2924 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2925 *non_exact_match = TRUE;
2926 return klass->interface_offsets_packed [i];
2934 print_implemented_interfaces (MonoClass *klass) {
2937 GPtrArray *ifaces = NULL;
2939 int ancestor_level = 0;
2941 name = mono_type_get_full_name (klass);
2942 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2945 for (i = 0; i < klass->interface_offsets_count; i++)
2946 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2947 klass->interfaces_packed [i]->interface_id,
2948 klass->interface_offsets_packed [i],
2949 klass->interfaces_packed [i]->method.count,
2950 klass->interfaces_packed [i]->name_space,
2951 klass->interfaces_packed [i]->name );
2952 printf ("Interface flags: ");
2953 for (i = 0; i <= klass->max_interface_id; i++)
2954 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2955 printf ("(%d,T)", i);
2957 printf ("(%d,F)", i);
2959 printf ("Dump interface flags:");
2960 #ifdef COMPRESSED_INTERFACE_BITMAP
2962 const uint8_t* p = klass->interface_bitmap;
2963 i = klass->max_interface_id;
2965 printf (" %d x 00 %02X", p [0], p [1]);
2971 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
2972 printf (" %02X", klass->interface_bitmap [i]);
2975 while (klass != NULL) {
2976 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
2977 ifaces = mono_class_get_implemented_interfaces (klass, &error);
2978 if (!mono_error_ok (&error)) {
2979 printf (" Type failed due to %s\n", mono_error_get_message (&error));
2980 mono_error_cleanup (&error);
2981 } else if (ifaces) {
2982 for (i = 0; i < ifaces->len; i++) {
2983 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
2984 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
2985 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2987 mono_class_interface_offset (klass, ic),
2992 g_ptr_array_free (ifaces, TRUE);
2995 klass = klass->parent;
3000 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
3003 args [0] = &arg0->byval_arg;
3005 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
3009 array_class_get_if_rank (MonoClass *klass, guint rank)
3011 return rank ? mono_array_class_get (klass, rank) : klass;
3015 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
3017 valuetype_types [0] = eclass;
3018 if (eclass == mono_defaults.int16_class)
3019 valuetype_types [1] = mono_defaults.uint16_class;
3020 else if (eclass == mono_defaults.uint16_class)
3021 valuetype_types [1] = mono_defaults.int16_class;
3022 else if (eclass == mono_defaults.int32_class)
3023 valuetype_types [1] = mono_defaults.uint32_class;
3024 else if (eclass == mono_defaults.uint32_class)
3025 valuetype_types [1] = mono_defaults.int32_class;
3026 else if (eclass == mono_defaults.int64_class)
3027 valuetype_types [1] = mono_defaults.uint64_class;
3028 else if (eclass == mono_defaults.uint64_class)
3029 valuetype_types [1] = mono_defaults.int64_class;
3030 else if (eclass == mono_defaults.byte_class)
3031 valuetype_types [1] = mono_defaults.sbyte_class;
3032 else if (eclass == mono_defaults.sbyte_class)
3033 valuetype_types [1] = mono_defaults.byte_class;
3034 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
3035 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
3038 /* this won't be needed once bug #325495 is completely fixed
3039 * though we'll need something similar to know which interfaces to allow
3040 * in arrays when they'll be lazyly created
3042 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
3043 * MS returns diferrent types based on which instance is called. For example:
3044 * object obj = new byte[10][];
3045 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
3046 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
3049 * Fixing this should kill quite some code, save some bits and improve compatibility.
3052 get_implicit_generic_array_interfaces (MonoClass *klass, int *num, int *is_enumerator)
3054 MonoClass *eclass = klass->element_class;
3055 static MonoClass* generic_icollection_class = NULL;
3056 static MonoClass* generic_ienumerable_class = NULL;
3057 static MonoClass* generic_ienumerator_class = NULL;
3058 static MonoClass* generic_ireadonlylist_class = NULL;
3059 static MonoClass* generic_ireadonlycollection_class = NULL;
3060 MonoClass *valuetype_types[2] = { NULL, NULL };
3061 MonoClass **interfaces = NULL;
3062 int i, nifaces, interface_count, real_count, original_rank;
3064 gboolean internal_enumerator;
3065 gboolean eclass_is_valuetype;
3067 if (!mono_defaults.generic_ilist_class) {
3071 internal_enumerator = FALSE;
3072 eclass_is_valuetype = FALSE;
3073 original_rank = eclass->rank;
3074 if (klass->byval_arg.type != MONO_TYPE_SZARRAY) {
3075 if (klass->generic_class && klass->nested_in == mono_defaults.array_class && strcmp (klass->name, "InternalEnumerator`1") == 0) {
3077 * For a Enumerator<T[]> we need to get the list of interfaces for T.
3079 eclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
3080 original_rank = eclass->rank;
3082 eclass = eclass->element_class;
3083 internal_enumerator = TRUE;
3084 *is_enumerator = TRUE;
3092 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
3093 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
3095 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
3097 if (!generic_icollection_class) {
3098 generic_icollection_class = mono_class_load_from_name (mono_defaults.corlib,
3099 "System.Collections.Generic", "ICollection`1");
3100 generic_ienumerable_class = mono_class_load_from_name (mono_defaults.corlib,
3101 "System.Collections.Generic", "IEnumerable`1");
3102 generic_ienumerator_class = mono_class_load_from_name (mono_defaults.corlib,
3103 "System.Collections.Generic", "IEnumerator`1");
3104 generic_ireadonlylist_class = mono_class_load_from_name (mono_defaults.corlib,
3105 "System.Collections.Generic", "IReadOnlyList`1");
3106 generic_ireadonlycollection_class = mono_class_load_from_name (mono_defaults.corlib,
3107 "System.Collections.Generic", "IReadOnlyCollection`1");
3110 mono_class_init (eclass);
3113 * Arrays in 2.0 need to implement a number of generic interfaces
3114 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
3115 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
3116 * We collect the types needed to build the
3117 * instantiations in interfaces at intervals of 3/5, because 3/5 are
3118 * the generic interfaces needed to implement.
3120 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
3121 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
3123 if (eclass->valuetype) {
3124 nifaces = generic_ireadonlylist_class ? 5 : 3;
3125 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
3127 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
3128 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
3129 if (internal_enumerator) {
3131 if (valuetype_types [1])
3135 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3136 interfaces [0] = valuetype_types [0];
3137 if (valuetype_types [1])
3138 interfaces [nifaces] = valuetype_types [1];
3140 eclass_is_valuetype = TRUE;
3143 int idepth = eclass->idepth;
3144 if (!internal_enumerator)
3146 nifaces = generic_ireadonlylist_class ? 2 : 3;
3148 // FIXME: This doesn't seem to work/required for generic params
3149 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
3150 mono_class_setup_interface_offsets (eclass);
3152 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
3153 /* we add object for interfaces and the supertypes for the other
3154 * types. The last of the supertypes is the element class itself which we
3155 * already created the explicit interfaces for (so we include it for IEnumerator
3156 * and exclude it for arrays).
3158 if (MONO_CLASS_IS_INTERFACE (eclass))
3161 interface_count += idepth;
3162 if (eclass->rank && eclass->element_class->valuetype) {
3163 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3164 if (valuetype_types [1])
3167 /* IList, ICollection, IEnumerable, IReadOnlyList */
3168 interface_count *= nifaces;
3169 real_count = interface_count;
3170 if (internal_enumerator) {
3171 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3172 if (valuetype_types [1])
3175 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3176 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3177 interfaces [0] = mono_defaults.object_class;
3181 for (i = 0; i < idepth; i++) {
3182 mono_class_init (eclass->supertypes [i]);
3183 interfaces [j] = eclass->supertypes [i];
3187 if (all_interfaces) {
3188 for (i = 0; i < eclass->interface_offsets_count; i++) {
3189 interfaces [j] = eclass->interfaces_packed [i];
3193 for (i = 0; i < eclass->interface_count; i++) {
3194 interfaces [j] = eclass->interfaces [i];
3198 if (valuetype_types [1]) {
3199 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3204 /* instantiate the generic interfaces */
3205 for (i = 0; i < interface_count; i += nifaces) {
3206 MonoClass *iface = interfaces [i];
3208 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3209 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3211 if (eclass->valuetype) {
3212 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3213 if (generic_ireadonlylist_class) {
3214 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3215 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3218 if (!generic_ireadonlylist_class)
3219 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3222 if (internal_enumerator) {
3224 /* instantiate IEnumerator<iface> */
3225 for (i = 0; i < interface_count; i++) {
3226 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3228 j = interface_count;
3229 if (!eclass_is_valuetype) {
3230 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3231 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3234 for (i = 0; i < eclass->idepth; i++) {
3235 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3239 for (i = 0; i < eclass->interface_offsets_count; i++) {
3240 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3244 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3246 if (valuetype_types [1])
3247 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3251 char *type_name = mono_type_get_name_full (&klass->byval_arg, 0);
3252 for (i = 0; i < real_count; ++i) {
3253 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3254 g_print ("%s implements %s\n", type_name, name);
3265 find_array_interface (MonoClass *klass, const char *name)
3268 for (i = 0; i < klass->interface_count; ++i) {
3269 if (strcmp (klass->interfaces [i]->name, name) == 0)
3276 * Return the number of virtual methods.
3277 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3278 * Return -1 on failure.
3279 * FIXME It would be nice if this information could be cached somewhere.
3282 count_virtual_methods (MonoClass *klass)
3286 klass = mono_class_get_generic_type_definition (klass); /*We can find this information by looking at the GTD*/
3288 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
3289 mono_class_setup_methods (klass);
3290 if (mono_class_has_failure (klass))
3293 for (i = 0; i < klass->method.count; ++i) {
3294 flags = klass->methods [i]->flags;
3295 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3299 for (i = 0; i < klass->method.count; ++i) {
3300 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
3302 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3310 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3318 m = (l + num_ifaces) / 2;
3319 if (interfaces_full [m] == ic)
3321 if (l == num_ifaces)
3323 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3332 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3334 int i = find_interface (num_ifaces, interfaces_full, ic);
3336 return interface_offsets_full [i];
3341 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3343 int i = find_interface (num_ifaces, interfaces_full, ic);
3347 interface_offsets_full [i] = offset;
3350 for (i = 0; i < num_ifaces; ++i) {
3351 if (interfaces_full [i]) {
3353 if (interfaces_full [i]->interface_id < ic->interface_id)
3356 while (end < num_ifaces && interfaces_full [end]) end++;
3357 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3358 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3360 interfaces_full [i] = ic;
3361 interface_offsets_full [i] = offset;
3367 #ifdef COMPRESSED_INTERFACE_BITMAP
3370 * Compressed interface bitmap design.
3372 * Interface bitmaps take a large amount of memory, because their size is
3373 * linear with the maximum interface id assigned in the process (each interface
3374 * is assigned a unique id as it is loaded). The number of interface classes
3375 * is high because of the many implicit interfaces implemented by arrays (we'll
3376 * need to lazy-load them in the future).
3377 * Most classes implement a very small number of interfaces, so the bitmap is
3378 * sparse. This bitmap needs to be checked by interface casts, so access to the
3379 * needed bit must be fast and doable with few jit instructions.
3381 * The current compression format is as follows:
3382 * *) it is a sequence of one or more two-byte elements
3383 * *) the first byte in the element is the count of empty bitmap bytes
3384 * at the current bitmap position
3385 * *) the second byte in the element is an actual bitmap byte at the current
3388 * As an example, the following compressed bitmap bytes:
3389 * 0x07 0x01 0x00 0x7
3390 * correspond to the following bitmap:
3391 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3393 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3394 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3395 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3399 * mono_compress_bitmap:
3400 * @dest: destination buffer
3401 * @bitmap: bitmap buffer
3402 * @size: size of @bitmap in bytes
3404 * This is a mono internal function.
3405 * The @bitmap data is compressed into a format that is small but
3406 * still searchable in few instructions by the JIT and runtime.
3407 * The compressed data is stored in the buffer pointed to by the
3408 * @dest array. Passing a #NULL value for @dest allows to just compute
3409 * the size of the buffer.
3410 * This compression algorithm assumes the bits set in the bitmap are
3411 * few and far between, like in interface bitmaps.
3412 * Returns: The size of the compressed bitmap in bytes.
3415 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3419 const uint8_t *end = bitmap + size;
3420 while (bitmap < end) {
3421 if (*bitmap || numz == 255) {
3445 * mono_class_interface_match:
3446 * @bitmap: a compressed bitmap buffer
3447 * @id: the index to check in the bitmap
3449 * This is a mono internal function.
3450 * Checks if a bit is set in a compressed interface bitmap. @id must
3451 * be already checked for being smaller than the maximum id encoded in the
3454 * Returns: A non-zero value if bit @id is set in the bitmap @bitmap,
3458 mono_class_interface_match (const uint8_t *bitmap, int id)
3461 id -= bitmap [0] * 8;
3465 return bitmap [1] & (1 << id);
3474 * LOCKING: this is supposed to be called with the loader lock held.
3475 * Return -1 on failure and set exception_type
3478 setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite)
3482 int i, j, max_iid, num_ifaces;
3483 MonoClass **interfaces_full = NULL;
3484 int *interface_offsets_full = NULL;
3486 GPtrArray **ifaces_array = NULL;
3487 int interface_offsets_count;
3488 MonoClass **array_interfaces = NULL;
3489 int num_array_interfaces;
3490 int is_enumerator = FALSE;
3492 mono_class_setup_supertypes (klass);
3494 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3495 * implicit interfaces have the property that they are assigned the same slot in the
3496 * vtables for compatible interfaces
3498 array_interfaces = get_implicit_generic_array_interfaces (klass, &num_array_interfaces, &is_enumerator);
3500 /* compute maximum number of slots and maximum interface id */
3502 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3503 ifaces_array = g_new0 (GPtrArray *, klass->idepth);
3504 for (j = 0; j < klass->idepth; j++) {
3505 k = klass->supertypes [j];
3506 num_ifaces += k->interface_count;
3507 for (i = 0; i < k->interface_count; i++) {
3508 ic = k->interfaces [i];
3511 mono_class_init (ic);
3513 if (max_iid < ic->interface_id)
3514 max_iid = ic->interface_id;
3516 ifaces = mono_class_get_implemented_interfaces (k, &error);
3517 if (!mono_error_ok (&error)) {
3518 char *name = mono_type_get_full_name (k);
3519 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)));
3521 mono_error_cleanup (&error);
3526 num_ifaces += ifaces->len;
3527 for (i = 0; i < ifaces->len; ++i) {
3528 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3529 if (max_iid < ic->interface_id)
3530 max_iid = ic->interface_id;
3532 ifaces_array [j] = ifaces;
3536 for (i = 0; i < num_array_interfaces; ++i) {
3537 ic = array_interfaces [i];
3538 mono_class_init (ic);
3539 if (max_iid < ic->interface_id)
3540 max_iid = ic->interface_id;
3543 if (MONO_CLASS_IS_INTERFACE (klass)) {
3545 if (max_iid < klass->interface_id)
3546 max_iid = klass->interface_id;
3548 klass->max_interface_id = max_iid;
3549 /* compute vtable offset for interfaces */
3550 interfaces_full = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3551 interface_offsets_full = (int *)g_malloc (sizeof (int) * num_ifaces);
3553 for (i = 0; i < num_ifaces; i++) {
3554 interface_offsets_full [i] = -1;
3557 /* skip the current class */
3558 for (j = 0; j < klass->idepth - 1; j++) {
3559 k = klass->supertypes [j];
3560 ifaces = ifaces_array [j];
3563 for (i = 0; i < ifaces->len; ++i) {
3565 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3567 /*Force the sharing of interface offsets between parent and subtypes.*/
3568 io = mono_class_interface_offset (k, ic);
3570 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3575 g_assert (klass == klass->supertypes [klass->idepth - 1]);
3576 ifaces = ifaces_array [klass->idepth - 1];
3578 for (i = 0; i < ifaces->len; ++i) {
3580 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3581 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3583 count = count_virtual_methods (ic);
3585 char *name = mono_type_get_full_name (ic);
3586 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error calculating interface offset of %s", name));
3595 if (MONO_CLASS_IS_INTERFACE (klass))
3596 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, klass, cur_slot, TRUE);
3598 if (num_array_interfaces) {
3599 if (is_enumerator) {
3600 int ienumerator_idx = find_array_interface (klass, "IEnumerator`1");
3601 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ienumerator_idx]);
3602 g_assert (ienumerator_offset >= 0);
3603 for (i = 0; i < num_array_interfaces; ++i) {
3604 ic = array_interfaces [i];
3605 if (strcmp (ic->name, "IEnumerator`1") == 0)
3606 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3608 g_assert_not_reached ();
3609 /*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);*/
3612 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3613 int ilist_iface_idx = find_array_interface (klass, "IList`1");
3614 MonoClass* ilist_class = klass->interfaces [ilist_iface_idx];
3615 int ireadonlylist_iface_idx = find_array_interface (klass, "IReadOnlyList`1");
3616 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? klass->interfaces [ireadonlylist_iface_idx] : NULL;
3617 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3618 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3619 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3620 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ilist_iface_idx]);
3621 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3622 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3623 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ireadonlylist_iface_idx]) : -1;
3624 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3625 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3626 for (i = 0; i < num_array_interfaces; ++i) {
3628 ic = array_interfaces [i];
3629 if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
3630 offset = ilist_offset;
3631 else if (strcmp (ic->name, "ICollection`1") == 0)
3632 offset = icollection_offset;
3633 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3634 offset = ienumerable_offset;
3635 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3636 offset = ireadonlylist_offset;
3637 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3638 offset = ireadonlycollection_offset;
3640 g_assert_not_reached ();
3641 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3642 /*g_print ("type %s has %s offset at %d (%s)\n", klass->name, ic->name, offset, klass->interfaces [0]->name);*/
3647 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3648 if (interface_offsets_full [i] != -1) {
3649 interface_offsets_count ++;
3654 * We might get called multiple times:
3655 * - mono_class_init ()
3656 * - mono_class_setup_vtable ().
3657 * - mono_class_setup_interface_offsets ().
3658 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3659 * means we have to overwrite those when called from other places (#4440).
3661 if (klass->interfaces_packed) {
3663 g_assert (klass->interface_offsets_count == interface_offsets_count);
3667 klass->interface_offsets_count = interface_offsets_count;
3668 klass->interfaces_packed = (MonoClass **)mono_class_alloc (klass, sizeof (MonoClass*) * interface_offsets_count);
3669 klass->interface_offsets_packed = (guint16 *)mono_class_alloc (klass, sizeof (guint16) * interface_offsets_count);
3670 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3671 #ifdef COMPRESSED_INTERFACE_BITMAP
3672 bitmap = g_malloc0 (bsize);
3674 bitmap = (uint8_t *)mono_class_alloc0 (klass, bsize);
3676 for (i = 0; i < interface_offsets_count; i++) {
3677 int id = interfaces_full [i]->interface_id;
3678 bitmap [id >> 3] |= (1 << (id & 7));
3679 klass->interfaces_packed [i] = interfaces_full [i];
3680 klass->interface_offsets_packed [i] = interface_offsets_full [i];
3681 /*if (num_array_interfaces)
3682 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]);*/
3684 #ifdef COMPRESSED_INTERFACE_BITMAP
3685 i = mono_compress_bitmap (NULL, bitmap, bsize);
3686 klass->interface_bitmap = mono_class_alloc0 (klass, i);
3687 mono_compress_bitmap (klass->interface_bitmap, bitmap, bsize);
3690 klass->interface_bitmap = bitmap;
3695 g_free (interfaces_full);
3696 g_free (interface_offsets_full);
3697 g_free (array_interfaces);
3698 for (i = 0; i < klass->idepth; i++) {
3699 ifaces = ifaces_array [i];
3701 g_ptr_array_free (ifaces, TRUE);
3703 g_free (ifaces_array);
3705 //printf ("JUST DONE: ");
3706 //print_implemented_interfaces (klass);
3712 * Setup interface offsets for interfaces.
3714 * - klass->max_interface_id
3715 * - klass->interface_offsets_count
3716 * - klass->interfaces_packed
3717 * - klass->interface_offsets_packed
3718 * - klass->interface_bitmap
3720 * This function can fail @class.
3723 mono_class_setup_interface_offsets (MonoClass *klass)
3725 mono_loader_lock ();
3727 setup_interface_offsets (klass, 0, FALSE);
3729 mono_loader_unlock ();
3732 /*Checks if @klass has @parent as one of it's parents type gtd
3736 * Bar<T> : Foo<Bar<Bar<T>>>
3740 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3742 klass = mono_class_get_generic_type_definition (klass);
3743 parent = mono_class_get_generic_type_definition (parent);
3744 mono_class_setup_supertypes (klass);
3745 mono_class_setup_supertypes (parent);
3747 return klass->idepth >= parent->idepth &&
3748 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3752 mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup)
3754 MonoGenericInst *ginst;
3756 if (!klass->generic_class) {
3757 mono_class_setup_vtable_full (klass, in_setup);
3758 return !mono_class_has_failure (klass);
3761 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup);
3762 if (mono_class_has_failure (klass->generic_class->container_class)) {
3763 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to load generic definition vtable"));
3767 ginst = klass->generic_class->context.class_inst;
3768 for (i = 0; i < ginst->type_argc; ++i) {
3770 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3772 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3773 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3774 if (mono_class_has_gtd_parent (klass, arg) || mono_class_has_gtd_parent (arg, klass))
3776 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3777 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Failed to load generic parameter %d", i));
3785 * mono_class_setup_vtable:
3787 * Creates the generic vtable of CLASS.
3788 * Initializes the following fields in MonoClass:
3791 * Plus all the fields initialized by setup_interface_offsets ().
3792 * If there is an error during vtable construction, klass->exception_type is set.
3794 * LOCKING: Acquires the loader lock.
3797 mono_class_setup_vtable (MonoClass *klass)
3799 mono_class_setup_vtable_full (klass, NULL);
3803 mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
3806 MonoMethod **overrides;
3807 MonoGenericContext *context;
3815 if (MONO_CLASS_IS_INTERFACE (klass)) {
3816 /* This sets method->slot for all methods if this is an interface */
3817 mono_class_setup_methods (klass);
3821 if (mono_class_has_failure (klass))
3824 if (g_list_find (in_setup, klass))
3827 mono_loader_lock ();
3829 if (klass->vtable) {
3830 mono_loader_unlock ();
3834 mono_stats.generic_vtable_count ++;
3835 in_setup = g_list_prepend (in_setup, klass);
3837 if (klass->generic_class) {
3838 if (!mono_class_check_vtable_constraints (klass, in_setup)) {
3839 mono_loader_unlock ();
3840 g_list_remove (in_setup, klass);
3844 context = mono_class_get_context (klass);
3845 type_token = klass->generic_class->container_class->type_token;
3847 context = (MonoGenericContext *) klass->generic_container;
3848 type_token = klass->type_token;
3851 if (image_is_dynamic (klass->image)) {
3852 /* Generic instances can have zero method overrides without causing any harm.
3853 * This is true since we don't do layout all over again for them, we simply inflate
3854 * the layout of the parent.
3856 mono_reflection_get_dynamic_overrides (klass, &overrides, &onum, &error);
3857 if (!is_ok (&error)) {
3858 mono_loader_unlock ();
3859 g_list_remove (in_setup, klass);
3860 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf("Could not load list of method overrides due to %s", mono_error_get_message (&error)));
3861 mono_error_cleanup (&error);
3865 /* The following call fails if there are missing methods in the type */
3866 /* FIXME it's probably a good idea to avoid this for generic instances. */
3867 ok = mono_class_get_overrides_full (klass->image, type_token, &overrides, &onum, context);
3871 mono_class_setup_vtable_general (klass, overrides, onum, in_setup);
3873 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load list of method overrides"));
3877 mono_loader_unlock ();
3878 g_list_remove (in_setup, klass);
3883 #define DEBUG_INTERFACE_VTABLE_CODE 0
3884 #define TRACE_INTERFACE_VTABLE_CODE 0
3885 #define VERIFY_INTERFACE_VTABLE_CODE 0
3886 #define VTABLE_SELECTOR (1)
3888 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3889 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3890 if (!(VTABLE_SELECTOR)) break; \
3894 #define DEBUG_INTERFACE_VTABLE(stmt)
3897 #if TRACE_INTERFACE_VTABLE_CODE
3898 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3899 if (!(VTABLE_SELECTOR)) break; \
3903 #define TRACE_INTERFACE_VTABLE(stmt)
3906 #if VERIFY_INTERFACE_VTABLE_CODE
3907 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3908 if (!(VTABLE_SELECTOR)) break; \
3912 #define VERIFY_INTERFACE_VTABLE(stmt)
3916 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3918 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3922 GString *res = g_string_new ("");
3924 g_string_append_c (res, '(');
3925 for (i = 0; i < sig->param_count; ++i) {
3927 g_string_append_c (res, ',');
3928 mono_type_get_desc (res, sig->params [i], include_namespace);
3930 g_string_append (res, ")=>");
3931 if (sig->ret != NULL) {
3932 mono_type_get_desc (res, sig->ret, include_namespace);
3934 g_string_append (res, "NULL");
3937 g_string_free (res, FALSE);
3941 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3942 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3943 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3944 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3952 is_wcf_hack_disabled (void)
3954 static gboolean disabled;
3955 static gboolean inited = FALSE;
3957 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3964 check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
3966 MonoMethodSignature *cmsig, *imsig;
3967 if (strcmp (im->name, cm->name) == 0) {
3968 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3969 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3972 if (! slot_is_empty) {
3973 if (require_newslot) {
3974 if (! interface_is_explicitly_implemented_by_class) {
3975 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3978 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3979 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3983 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3986 cmsig = mono_method_signature (cm);
3987 imsig = mono_method_signature (im);
3988 if (!cmsig || !imsig) {
3989 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3993 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3994 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3995 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3996 TRACE_INTERFACE_VTABLE (printf ("]"));
3999 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
4000 if (mono_security_core_clr_enabled ())
4001 mono_security_core_clr_check_override (klass, cm, im);
4003 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
4004 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4005 char *body_name = mono_method_full_name (cm, TRUE);
4006 char *decl_name = mono_method_full_name (im, TRUE);
4007 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));
4015 MonoClass *ic = im->klass;
4016 const char *ic_name_space = ic->name_space;
4017 const char *ic_name = ic->name;
4020 if (! require_newslot) {
4021 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
4024 if (cm->klass->rank == 0) {
4025 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
4028 cmsig = mono_method_signature (cm);
4029 imsig = mono_method_signature (im);
4030 if (!cmsig || !imsig) {
4031 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
4035 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4036 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
4037 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4038 TRACE_INTERFACE_VTABLE (printf ("]"));
4041 if (mono_class_get_image (ic) != mono_defaults.corlib) {
4042 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
4045 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
4046 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
4049 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))) {
4050 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
4054 subname = strstr (cm->name, ic_name_space);
4055 if (subname != cm->name) {
4056 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
4059 subname += strlen (ic_name_space);
4060 if (subname [0] != '.') {
4061 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
4065 if (strstr (subname, ic_name) != subname) {
4066 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
4069 subname += strlen (ic_name);
4070 if (subname [0] != '.') {
4071 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
4075 if (strcmp (subname, im->name) != 0) {
4076 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
4080 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
4081 if (mono_security_core_clr_enabled ())
4082 mono_security_core_clr_check_override (klass, cm, im);
4084 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
4085 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4086 char *body_name = mono_method_full_name (cm, TRUE);
4087 char *decl_name = mono_method_full_name (im, TRUE);
4088 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));
4098 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
4100 foreach_override (gpointer key, gpointer value, gpointer user_data) {
4101 MonoMethod *method = key;
4102 MonoMethod *override = value;
4103 MonoClass *method_class = mono_method_get_class (method);
4104 MonoClass *override_class = mono_method_get_class (override);
4106 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
4107 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
4108 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
4111 print_overrides (GHashTable *override_map, const char *message) {
4113 printf ("Override map \"%s\" START:\n", message);
4114 g_hash_table_foreach (override_map, foreach_override, NULL);
4115 printf ("Override map \"%s\" END.\n", message);
4117 printf ("Override map \"%s\" EMPTY.\n", message);
4121 print_vtable_full (MonoClass *klass, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
4122 char *full_name = mono_type_full_name (&klass->byval_arg);
4126 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
4128 if (print_interfaces) {
4129 print_implemented_interfaces (klass);
4130 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
4133 if (klass->parent) {
4134 parent_size = klass->parent->vtable_size;
4138 for (i = 0; i < size; ++i) {
4139 MonoMethod *cm = vtable [i];
4140 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
4141 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
4143 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
4151 #if VERIFY_INTERFACE_VTABLE_CODE
4153 mono_method_try_get_vtable_index (MonoMethod *method)
4155 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4156 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4157 if (imethod->declaring->is_generic)
4158 return imethod->declaring->slot;
4160 return method->slot;
4164 mono_class_verify_vtable (MonoClass *klass)
4167 char *full_name = mono_type_full_name (&klass->byval_arg);
4169 printf ("*** Verifying VTable of class '%s' \n", full_name);
4173 if (!klass->methods)
4176 for (i = 0; i < klass->method.count; ++i) {
4177 MonoMethod *cm = klass->methods [i];
4180 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4184 full_name = mono_method_full_name (cm, TRUE);
4186 slot = mono_method_try_get_vtable_index (cm);
4188 if (slot >= klass->vtable_size) {
4189 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, klass->vtable_size);
4193 if (slot >= 0 && klass->vtable [slot] != cm && (klass->vtable [slot])) {
4194 char *other_name = klass->vtable [slot] ? mono_method_full_name (klass->vtable [slot], TRUE) : g_strdup ("[null value]");
4195 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4196 g_free (other_name);
4199 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4206 print_unimplemented_interface_method_info (MonoClass *klass, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4208 char *method_signature;
4211 for (index = 0; index < onum; ++index) {
4212 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4213 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4215 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4216 type_name = mono_type_full_name (&klass->byval_arg);
4217 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4218 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4219 g_free (method_signature);
4221 mono_class_setup_methods (klass);
4222 if (mono_class_has_failure (klass)) {
4223 char *name = mono_type_get_full_name (klass);
4224 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4228 for (index = 0; index < klass->method.count; ++index) {
4229 MonoMethod *cm = klass->methods [index];
4230 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4232 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4233 g_free (method_signature);
4238 mono_method_get_method_definition (MonoMethod *method)
4240 while (method->is_inflated)
4241 method = ((MonoMethodInflated*)method)->declaring;
4246 verify_class_overrides (MonoClass *klass, MonoMethod **overrides, int onum)
4250 for (i = 0; i < onum; ++i) {
4251 MonoMethod *decl = overrides [i * 2];
4252 MonoMethod *body = overrides [i * 2 + 1];
4254 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (klass)) {
4255 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method belongs to a different class than the declared one"));
4259 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4260 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4261 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must not be static to override a base type"));
4263 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must be virtual to override a base type"));
4267 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4268 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4269 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a static method in a base type"));
4271 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a non virtual method in a base type"));
4275 if (!mono_class_is_assignable_from_slow (decl->klass, klass)) {
4276 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"));
4280 body = mono_method_get_method_definition (body);
4281 decl = mono_method_get_method_definition (decl);
4283 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4284 char *body_name = mono_method_full_name (body, TRUE);
4285 char *decl_name = mono_method_full_name (decl, TRUE);
4286 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));
4296 mono_class_need_stelemref_method (MonoClass *klass)
4298 return klass->rank == 1 && MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg);
4302 * LOCKING: this is supposed to be called with the loader lock held.
4305 mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int onum, GList *in_setup)
4309 MonoMethod **vtable;
4310 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4311 GPtrArray *ifaces = NULL;
4312 GHashTable *override_map = NULL;
4314 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4315 int first_non_interface_slot;
4317 GSList *virt_methods = NULL, *l;
4318 int stelemref_slot = 0;
4323 if (overrides && !verify_class_overrides (klass, overrides, onum))
4326 ifaces = mono_class_get_implemented_interfaces (klass, &error);
4327 if (!mono_error_ok (&error)) {
4328 char *name = mono_type_get_full_name (klass);
4329 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)));
4331 mono_error_cleanup (&error);
4333 } else if (ifaces) {
4334 for (i = 0; i < ifaces->len; i++) {
4335 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
4336 max_vtsize += ic->method.count;
4338 g_ptr_array_free (ifaces, TRUE);
4342 if (klass->parent) {
4343 mono_class_init (klass->parent);
4344 mono_class_setup_vtable_full (klass->parent, in_setup);
4346 if (mono_class_has_failure (klass->parent)) {
4347 char *name = mono_type_get_full_name (klass->parent);
4348 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Parent %s failed to load", name));
4353 max_vtsize += klass->parent->vtable_size;
4354 cur_slot = klass->parent->vtable_size;
4357 max_vtsize += klass->method.count;
4359 /*Array have a slot for stelemref*/
4360 if (mono_class_need_stelemref_method (klass)) {
4361 stelemref_slot = cur_slot;
4366 vtable = (MonoMethod **)alloca (sizeof (gpointer) * max_vtsize);
4367 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4369 /* printf ("METAINIT %s.%s\n", klass->name_space, klass->name); */
4371 cur_slot = setup_interface_offsets (klass, cur_slot, TRUE);
4372 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4375 max_iid = klass->max_interface_id;
4376 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4378 /* Optimized version for generic instances */
4379 if (klass->generic_class) {
4381 MonoClass *gklass = klass->generic_class->container_class;
4384 mono_class_setup_vtable_full (gklass, in_setup);
4385 if (mono_class_has_failure (gklass)) {
4386 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
4390 tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * gklass->vtable_size);
4391 klass->vtable_size = gklass->vtable_size;
4392 for (i = 0; i < gklass->vtable_size; ++i)
4393 if (gklass->vtable [i]) {
4394 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], klass, mono_class_get_context (klass), &error);
4395 if (!mono_error_ok (&error)) {
4396 char *err_msg = g_strdup_printf ("Could not inflate method due to %s", mono_error_get_message (&error));
4397 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
4399 mono_error_cleanup (&error);
4403 tmp [i]->slot = gklass->vtable [i]->slot;
4405 mono_memory_barrier ();
4406 klass->vtable = tmp;
4408 /* Have to set method->slot for abstract virtual methods */
4409 if (klass->methods && gklass->methods) {
4410 for (i = 0; i < klass->method.count; ++i)
4411 if (klass->methods [i]->slot == -1)
4412 klass->methods [i]->slot = gklass->methods [i]->slot;
4418 if (klass->parent && klass->parent->vtable_size) {
4419 MonoClass *parent = klass->parent;
4422 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4424 // Also inherit parent interface vtables, just as a starting point.
4425 // This is needed otherwise bug-77127.exe fails when the property methods
4426 // have different names in the iterface and the class, because for child
4427 // classes the ".override" information is not used anymore.
4428 for (i = 0; i < parent->interface_offsets_count; i++) {
4429 MonoClass *parent_interface = parent->interfaces_packed [i];
4430 int interface_offset = mono_class_interface_offset (klass, parent_interface);
4431 /*FIXME this is now dead code as this condition will never hold true.
4432 Since interface offsets are inherited then the offset of an interface implemented
4433 by a parent will never be the out of it's vtable boundary.
4435 if (interface_offset >= parent->vtable_size) {
4436 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4439 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4440 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4441 for (j = 0; j < parent_interface->method.count && !mono_class_has_failure (klass); j++) {
4442 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4443 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4444 parent_interface_offset + j, parent_interface_offset, j,
4445 interface_offset + j, interface_offset, j));
4452 /*Array have a slot for stelemref*/
4453 if (mono_class_need_stelemref_method (klass)) {
4454 MonoMethod *method = mono_marshal_get_virtual_stelemref (klass);
4456 method->slot = stelemref_slot;
4458 g_assert (method->slot == stelemref_slot);
4460 vtable [stelemref_slot] = method;
4463 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4464 /* override interface methods */
4465 for (i = 0; i < onum; i++) {
4466 MonoMethod *decl = overrides [i*2];
4467 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4469 dslot = mono_method_get_vtable_slot (decl);
4471 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
4475 dslot += mono_class_interface_offset (klass, decl->klass);
4476 vtable [dslot] = overrides [i*2 + 1];
4477 vtable [dslot]->slot = dslot;
4479 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4481 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4483 if (mono_security_core_clr_enabled ())
4484 mono_security_core_clr_check_override (klass, vtable [dslot], decl);
4487 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4488 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4491 * Create a list of virtual methods to avoid calling
4492 * mono_class_get_virtual_methods () which is slow because of the metadata
4496 gpointer iter = NULL;
4499 virt_methods = NULL;
4500 while ((cm = mono_class_get_virtual_methods (klass, &iter))) {
4501 virt_methods = g_slist_prepend (virt_methods, cm);
4503 if (mono_class_has_failure (klass))
4507 // Loop on all implemented interfaces...
4508 for (i = 0; i < klass->interface_offsets_count; i++) {
4509 MonoClass *parent = klass->parent;
4511 gboolean interface_is_explicitly_implemented_by_class;
4514 ic = klass->interfaces_packed [i];
4515 ic_offset = mono_class_interface_offset (klass, ic);
4517 mono_class_setup_methods (ic);
4518 if (mono_class_has_failure (ic))
4521 // Check if this interface is explicitly implemented (instead of just inherited)
4522 if (parent != NULL) {
4523 int implemented_interfaces_index;
4524 interface_is_explicitly_implemented_by_class = FALSE;
4525 for (implemented_interfaces_index = 0; implemented_interfaces_index < klass->interface_count; implemented_interfaces_index++) {
4526 if (ic == klass->interfaces [implemented_interfaces_index]) {
4527 interface_is_explicitly_implemented_by_class = TRUE;
4532 interface_is_explicitly_implemented_by_class = TRUE;
4535 // Loop on all interface methods...
4536 for (im_index = 0; im_index < ic->method.count; im_index++) {
4537 MonoMethod *im = ic->methods [im_index];
4538 int im_slot = ic_offset + im->slot;
4539 MonoMethod *override_im = (override_map != NULL) ? (MonoMethod *)g_hash_table_lookup (override_map, im) : NULL;
4541 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4544 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4546 // If there is an explicit implementation, just use it right away,
4547 // otherwise look for a matching method
4548 if (override_im == NULL) {
4552 // First look for a suitable method among the class methods
4553 for (l = virt_methods; l; l = l->next) {
4554 cm = (MonoMethod *)l->data;
4555 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)));
4556 if (check_interface_method_override (klass, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
4557 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4558 vtable [im_slot] = cm;
4559 /* Why do we need this? */
4564 TRACE_INTERFACE_VTABLE (printf ("\n"));
4565 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4569 // If the slot is still empty, look in all the inherited virtual methods...
4570 if ((vtable [im_slot] == NULL) && klass->parent != NULL) {
4571 MonoClass *parent = klass->parent;
4572 // Reverse order, so that last added methods are preferred
4573 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4574 MonoMethod *cm = parent->vtable [cm_index];
4576 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));
4577 if ((cm != NULL) && check_interface_method_override (klass, im, cm, FALSE, FALSE, TRUE)) {
4578 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4579 vtable [im_slot] = cm;
4580 /* Why do we need this? */
4586 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4588 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4592 g_assert (vtable [im_slot] == override_im);
4597 // If the class is not abstract, check that all its interface slots are full.
4598 // The check is done here and not directly at the end of the loop above because
4599 // it can happen (for injected generic array interfaces) that the same slot is
4600 // processed multiple times (those interfaces have overlapping slots), and it
4601 // will not always be the first pass the one that fills the slot.
4602 if (! (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4603 for (i = 0; i < klass->interface_offsets_count; i++) {
4607 ic = klass->interfaces_packed [i];
4608 ic_offset = mono_class_interface_offset (klass, ic);
4610 for (im_index = 0; im_index < ic->method.count; im_index++) {
4611 MonoMethod *im = ic->methods [im_index];
4612 int im_slot = ic_offset + im->slot;
4614 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4617 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4618 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4619 if (vtable [im_slot] == NULL) {
4620 print_unimplemented_interface_method_info (klass, ic, im, im_slot, overrides, onum);
4627 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4628 for (l = virt_methods; l; l = l->next) {
4629 cm = (MonoMethod *)l->data;
4631 * If the method is REUSE_SLOT, we must check in the
4632 * base class for a method to override.
4634 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4636 for (k = klass->parent; k ; k = k->parent) {
4641 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4642 MonoMethodSignature *cmsig, *m1sig;
4644 cmsig = mono_method_signature (cm);
4645 m1sig = mono_method_signature (m1);
4647 if (!cmsig || !m1sig) {
4648 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
4652 if (!strcmp(cm->name, m1->name) &&
4653 mono_metadata_signature_equal (cmsig, m1sig)) {
4655 if (mono_security_core_clr_enabled ())
4656 mono_security_core_clr_check_override (klass, cm, m1);
4658 slot = mono_method_get_vtable_slot (m1);
4662 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4663 char *body_name = mono_method_full_name (cm, TRUE);
4664 char *decl_name = mono_method_full_name (m1, TRUE);
4665 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));
4671 g_assert (cm->slot < max_vtsize);
4673 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4674 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4675 mono_method_full_name (m1, 1), m1,
4676 mono_method_full_name (cm, 1), cm));
4677 g_hash_table_insert (override_map, m1, cm);
4681 if (mono_class_has_failure (k))
4691 /*Non final newslot methods must be given a non-interface vtable slot*/
4692 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4696 cm->slot = cur_slot++;
4698 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4699 vtable [cm->slot] = cm;
4702 /* override non interface methods */
4703 for (i = 0; i < onum; i++) {
4704 MonoMethod *decl = overrides [i*2];
4705 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4706 g_assert (decl->slot != -1);
4707 vtable [decl->slot] = overrides [i*2 + 1];
4708 overrides [i * 2 + 1]->slot = decl->slot;
4710 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4711 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4712 mono_method_full_name (decl, 1), decl,
4713 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4714 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4716 if (mono_security_core_clr_enabled ())
4717 mono_security_core_clr_check_override (klass, vtable [decl->slot], decl);
4722 * If a method occupies more than one place in the vtable, and it is
4723 * overriden, then change the other occurances too.
4728 for (i = 0; i < max_vtsize; ++i)
4730 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4732 cm = (MonoMethod *)g_hash_table_lookup (override_map, vtable [i]);
4737 g_hash_table_destroy (override_map);
4738 override_map = NULL;
4741 g_slist_free (virt_methods);
4742 virt_methods = NULL;
4744 /* Ensure that all vtable slots are filled with concrete instance methods */
4745 if (!(klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4746 for (i = 0; i < cur_slot; ++i) {
4747 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4748 char *type_name = mono_type_get_full_name (klass);
4749 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4750 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));
4752 g_free (method_name);
4758 if (klass->generic_class) {
4759 MonoClass *gklass = klass->generic_class->container_class;
4761 mono_class_init (gklass);
4763 klass->vtable_size = MAX (gklass->vtable_size, cur_slot);
4765 /* Check that the vtable_size value computed in mono_class_init () is correct */
4766 if (klass->vtable_size)
4767 g_assert (cur_slot == klass->vtable_size);
4768 klass->vtable_size = cur_slot;
4771 /* Try to share the vtable with our parent. */
4772 if (klass->parent && (klass->parent->vtable_size == klass->vtable_size) && (memcmp (klass->parent->vtable, vtable, sizeof (gpointer) * klass->vtable_size) == 0)) {
4773 mono_memory_barrier ();
4774 klass->vtable = klass->parent->vtable;
4776 MonoMethod **tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * klass->vtable_size);
4777 memcpy (tmp, vtable, sizeof (gpointer) * klass->vtable_size);
4778 mono_memory_barrier ();
4779 klass->vtable = tmp;
4782 DEBUG_INTERFACE_VTABLE (print_vtable_full (klass, klass->vtable, klass->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4783 if (mono_print_vtable) {
4786 print_implemented_interfaces (klass);
4788 for (i = 0; i <= max_iid; i++)
4789 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
4792 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&klass->byval_arg),
4793 klass->vtable_size, icount);
4795 for (i = 0; i < cur_slot; ++i) {
4800 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4801 mono_method_full_name (cm, TRUE));
4807 printf ("Interfaces %s.%s (max_iid = %d)\n", klass->name_space,
4808 klass->name, max_iid);
4810 for (i = 0; i < klass->interface_count; i++) {
4811 ic = klass->interfaces [i];
4812 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4813 mono_class_interface_offset (klass, ic),
4814 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4817 for (k = klass->parent; k ; k = k->parent) {
4818 for (i = 0; i < k->interface_count; i++) {
4819 ic = k->interfaces [i];
4820 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4821 mono_class_interface_offset (klass, ic),
4822 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4828 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (klass));
4833 char *name = mono_type_get_full_name (klass);
4834 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("VTable setup of type %s failed", name));
4837 g_hash_table_destroy (override_map);
4839 g_slist_free (virt_methods);
4844 * mono_method_get_vtable_slot:
4846 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4847 * LOCKING: Acquires the loader lock.
4849 * FIXME Use proper MonoError machinery here.
4852 mono_method_get_vtable_slot (MonoMethod *method)
4854 if (method->slot == -1) {
4855 mono_class_setup_vtable (method->klass);
4856 if (mono_class_has_failure (method->klass))
4858 if (method->slot == -1) {
4862 if (!method->klass->generic_class) {
4863 g_assert (method->is_inflated);
4864 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4867 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4868 g_assert (method->klass->generic_class);
4869 gklass = method->klass->generic_class->container_class;
4870 mono_class_setup_methods (method->klass);
4871 g_assert (method->klass->methods);
4872 for (i = 0; i < method->klass->method.count; ++i) {
4873 if (method->klass->methods [i] == method)
4876 g_assert (i < method->klass->method.count);
4877 g_assert (gklass->methods);
4878 method->slot = gklass->methods [i]->slot;
4880 g_assert (method->slot != -1);
4882 return method->slot;
4886 * mono_method_get_vtable_index:
4889 * Returns the index into the runtime vtable to access the method or,
4890 * in the case of a virtual generic method, the virtual generic method
4891 * thunk. Returns -1 on failure.
4893 * FIXME Use proper MonoError machinery here.
4896 mono_method_get_vtable_index (MonoMethod *method)
4898 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4899 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4900 if (imethod->declaring->is_generic)
4901 return mono_method_get_vtable_slot (imethod->declaring);
4903 return mono_method_get_vtable_slot (method);
4906 static MonoMethod *default_ghc = NULL;
4907 static MonoMethod *default_finalize = NULL;
4908 static int finalize_slot = -1;
4909 static int ghc_slot = -1;
4912 initialize_object_slots (MonoClass *klass)
4917 if (klass == mono_defaults.object_class) {
4918 mono_class_setup_vtable (klass);
4919 for (i = 0; i < klass->vtable_size; ++i) {
4920 MonoMethod *cm = klass->vtable [i];
4922 if (!strcmp (cm->name, "GetHashCode"))
4924 else if (!strcmp (cm->name, "Finalize"))
4928 g_assert (ghc_slot > 0);
4929 default_ghc = klass->vtable [ghc_slot];
4931 g_assert (finalize_slot > 0);
4932 default_finalize = klass->vtable [finalize_slot];
4937 MonoMethod *array_method;
4939 } GenericArrayMethodInfo;
4941 static int generic_array_method_num = 0;
4942 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4945 generic_array_methods (MonoClass *klass)
4947 int i, count_generic = 0;
4948 GList *list = NULL, *tmp;
4949 if (generic_array_method_num)
4950 return generic_array_method_num;
4951 mono_class_setup_methods (klass->parent); /*This is setting up System.Array*/
4952 g_assert (!mono_class_has_failure (klass->parent)); /*So hitting this assert is a huge problem*/
4953 for (i = 0; i < klass->parent->method.count; i++) {
4954 MonoMethod *m = klass->parent->methods [i];
4955 if (!strncmp (m->name, "InternalArray__", 15)) {
4957 list = g_list_prepend (list, m);
4960 list = g_list_reverse (list);
4961 generic_array_method_info = (GenericArrayMethodInfo *)mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4963 for (tmp = list; tmp; tmp = tmp->next) {
4964 const char *mname, *iname;
4966 MonoMethod *m = (MonoMethod *)tmp->data;
4967 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4968 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4970 generic_array_method_info [i].array_method = m;
4971 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4972 iname = "System.Collections.Generic.ICollection`1.";
4973 mname = m->name + 27;
4974 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4975 iname = "System.Collections.Generic.IEnumerable`1.";
4976 mname = m->name + 27;
4977 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4978 iname = "System.Collections.Generic.IReadOnlyList`1.";
4979 mname = m->name + strlen (ireadonlylist_prefix);
4980 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4981 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4982 mname = m->name + strlen (ireadonlycollection_prefix);
4983 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4984 iname = "System.Collections.Generic.IList`1.";
4985 mname = m->name + 15;
4987 g_assert_not_reached ();
4990 name = (gchar *)mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4991 strcpy (name, iname);
4992 strcpy (name + strlen (iname), mname);
4993 generic_array_method_info [i].name = name;
4996 /*g_print ("array generic methods: %d\n", count_generic);*/
4998 generic_array_method_num = count_generic;
5000 return generic_array_method_num;
5004 setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos)
5006 MonoGenericContext tmp_context;
5009 tmp_context.class_inst = NULL;
5010 tmp_context.method_inst = iface->generic_class->context.class_inst;
5011 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
5013 for (i = 0; i < generic_array_method_num; i++) {
5015 MonoMethod *m = generic_array_method_info [i].array_method;
5016 MonoMethod *inflated;
5018 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
5019 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
5020 methods [pos++] = mono_marshal_get_generic_array_helper (klass, iface, generic_array_method_info [i].name, inflated);
5025 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
5027 int null_length = strlen ("(null)");
5028 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
5029 char *s = (char *)mono_image_alloc (image, len);
5032 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
5033 g_assert (result == len - 1);
5039 set_failure_from_loader_error (MonoClass *klass, MonoLoaderError *error)
5041 gpointer exception_data = NULL;
5043 switch (error->exception_type) {
5044 case MONO_EXCEPTION_TYPE_LOAD:
5045 exception_data = concat_two_strings_with_zero (klass->image, error->class_name, error->assembly_name);
5048 case MONO_EXCEPTION_MISSING_METHOD:
5049 exception_data = concat_two_strings_with_zero (klass->image, error->class_name, error->member_name);
5052 case MONO_EXCEPTION_MISSING_FIELD: {
5053 const char *name_space = error->klass->name_space ? error->klass->name_space : NULL;
5054 const char *class_name;
5057 class_name = g_strdup_printf ("%s.%s", name_space, error->klass->name);
5059 class_name = error->klass->name;
5061 exception_data = concat_two_strings_with_zero (klass->image, class_name, error->member_name);
5064 g_free ((void*)class_name);
5068 case MONO_EXCEPTION_FILE_NOT_FOUND: {
5071 if (error->ref_only)
5072 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.";
5074 msg = "Could not load file or assembly '%s' or one of its dependencies.";
5076 exception_data = concat_two_strings_with_zero (klass->image, msg, error->assembly_name);
5080 case MONO_EXCEPTION_BAD_IMAGE:
5081 exception_data = error->msg;
5085 g_assert_not_reached ();
5088 mono_class_set_failure (klass, error->exception_type, exception_data);
5093 * @class: the class to initialize
5095 * Compute the instance_size, class_size and other infos that cannot be
5096 * computed at mono_class_get() time. Also compute vtable_size if possible.
5097 * Returns TRUE on success or FALSE if there was a problem in loading
5098 * the type (incorrect assemblies, missing assemblies, methods, etc).
5100 * LOCKING: Acquires the loader lock.
5103 mono_class_init (MonoClass *klass)
5106 MonoCachedClassInfo cached_info;
5107 gboolean has_cached_info;
5111 /* Double-checking locking pattern */
5112 if (klass->inited || mono_class_has_failure (klass))
5113 return !mono_class_has_failure (klass);
5115 /*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/
5117 /* We do everything inside the lock to prevent races */
5118 mono_loader_lock ();
5120 if (klass->inited || mono_class_has_failure (klass)) {
5121 mono_loader_unlock ();
5122 /* Somebody might have gotten in before us */
5123 return !mono_class_has_failure (klass);
5126 if (klass->init_pending) {
5127 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Recursive type definition detected"));
5131 klass->init_pending = 1;
5133 if (mono_verifier_is_enabled_for_class (klass) && !mono_verifier_verify_class (klass)) {
5134 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, concat_two_strings_with_zero (klass->image, klass->name, klass->image->assembly_name));
5139 if (klass->byval_arg.type == MONO_TYPE_ARRAY || klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5140 MonoClass *element_class = klass->element_class;
5141 if (!element_class->inited)
5142 mono_class_init (element_class);
5143 if (mono_class_has_failure (element_class)) {
5144 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5149 mono_stats.initialized_class_count++;
5151 if (klass->generic_class && !klass->generic_class->is_dynamic) {
5152 MonoClass *gklass = klass->generic_class->container_class;
5154 mono_stats.generic_class_count++;
5156 klass->method = gklass->method;
5157 klass->field = gklass->field;
5159 mono_class_init (gklass);
5160 // FIXME: Why is this needed ?
5161 if (!mono_class_has_failure (gklass))
5162 mono_class_setup_methods (gklass);
5163 if (mono_class_has_failure (gklass)) {
5164 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic Type Defintion failed to init"));
5168 if (MONO_CLASS_IS_INTERFACE (klass))
5169 klass->interface_id = mono_get_unique_iid (klass);
5172 if (klass->parent && !klass->parent->inited)
5173 mono_class_init (klass->parent);
5175 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
5177 if (klass->generic_class || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
5178 klass->nested_classes_inited = TRUE;
5181 * Computes the size used by the fields, and their locations
5183 if (has_cached_info) {
5184 klass->instance_size = cached_info.instance_size;
5185 klass->sizes.class_size = cached_info.class_size;
5186 klass->packing_size = cached_info.packing_size;
5187 klass->min_align = cached_info.min_align;
5188 klass->blittable = cached_info.blittable;
5189 klass->has_references = cached_info.has_references;
5190 klass->has_static_refs = cached_info.has_static_refs;
5191 klass->no_special_static_fields = cached_info.no_special_static_fields;
5194 if (!klass->size_inited){
5195 mono_class_setup_fields (klass);
5196 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
5200 /* Initialize arrays */
5202 klass->method.count = 3 + (klass->rank > 1? 2: 1);
5204 if (klass->interface_count) {
5205 int count_generic = generic_array_methods (klass);
5206 klass->method.count += klass->interface_count * count_generic;
5210 mono_class_setup_supertypes (klass);
5213 initialize_object_slots (klass);
5216 * Initialize the rest of the data without creating a generic vtable if possible.
5217 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5218 * also avoid computing a generic vtable.
5220 if (has_cached_info) {
5222 klass->vtable_size = cached_info.vtable_size;
5223 klass->has_finalize = cached_info.has_finalize;
5224 klass->has_finalize_inited = TRUE;
5225 klass->ghcimpl = cached_info.ghcimpl;
5226 klass->has_cctor = cached_info.has_cctor;
5227 } else if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5228 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5229 * The first slot if for array with.
5231 static int szarray_vtable_size[2] = { 0 };
5233 int slot = MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg) ? 0 : 1;
5236 if (!szarray_vtable_size [slot]) {
5237 mono_class_setup_vtable (klass);
5238 szarray_vtable_size [slot] = klass->vtable_size;
5240 klass->vtable_size = szarray_vtable_size[slot];
5242 } else if (klass->generic_class && !MONO_CLASS_IS_INTERFACE (klass)) {
5243 MonoClass *gklass = klass->generic_class->container_class;
5245 /* Generic instance case */
5246 klass->ghcimpl = gklass->ghcimpl;
5247 klass->has_cctor = gklass->has_cctor;
5249 mono_class_setup_vtable (gklass);
5250 if (mono_class_has_failure (gklass)) {
5251 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5255 klass->vtable_size = gklass->vtable_size;
5259 /* ghcimpl is not currently used
5261 if (klass->parent) {
5262 MonoMethod *cmethod = klass->vtable [ghc_slot];
5263 if (cmethod->is_inflated)
5264 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5265 if (cmethod == default_ghc) {
5271 /* C# doesn't allow interfaces to have cctors */
5272 if (!MONO_CLASS_IS_INTERFACE (klass) || klass->image != mono_defaults.corlib) {
5273 MonoMethod *cmethod = NULL;
5275 if (klass->type_token && !image_is_dynamic(klass->image)) {
5276 cmethod = find_method_in_metadata (klass, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5277 /* The find_method function ignores the 'flags' argument */
5278 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5279 klass->has_cctor = 1;
5281 mono_class_setup_methods (klass);
5282 if (mono_class_has_failure (klass))
5285 for (i = 0; i < klass->method.count; ++i) {
5286 MonoMethod *method = klass->methods [i];
5287 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5288 (strcmp (".cctor", method->name) == 0)) {
5289 klass->has_cctor = 1;
5297 if (klass->parent) {
5298 int first_iface_slot;
5299 /* This will compute klass->parent->vtable_size for some classes */
5300 mono_class_init (klass->parent);
5301 if (mono_class_has_failure (klass->parent)) {
5302 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5305 if (mono_loader_get_last_error ())
5307 if (!klass->parent->vtable_size) {
5308 /* FIXME: Get rid of this somehow */
5309 mono_class_setup_vtable (klass->parent);
5310 if (mono_class_has_failure (klass->parent)) {
5311 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5314 if (mono_loader_get_last_error ())
5317 first_iface_slot = klass->parent->vtable_size;
5318 if (mono_class_need_stelemref_method (klass))
5320 setup_interface_offsets (klass, first_iface_slot, TRUE);
5322 setup_interface_offsets (klass, 0, TRUE);
5325 if (mono_security_core_clr_enabled ())
5326 mono_security_core_clr_check_inheritance (klass);
5328 if (mono_loader_get_last_error ()) {
5329 if (!mono_class_has_failure (klass)) {
5330 set_failure_from_loader_error (klass, mono_loader_get_last_error ());
5332 mono_loader_clear_error ();
5335 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass))
5336 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Invalid generic instantiation"));
5341 /* Because of the double-checking locking pattern */
5342 mono_memory_barrier ();
5344 klass->init_pending = 0;
5346 mono_loader_unlock ();
5348 return !mono_class_has_failure (klass);
5352 * mono_class_has_finalizer:
5354 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5358 mono_class_has_finalizer (MonoClass *klass)
5360 gboolean has_finalize = FALSE;
5362 if (klass->has_finalize_inited)
5363 return klass->has_finalize;
5365 /* Interfaces and valuetypes are not supposed to have finalizers */
5366 if (!(MONO_CLASS_IS_INTERFACE (klass) || klass->valuetype)) {
5367 MonoMethod *cmethod = NULL;
5369 if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5370 } else if (klass->generic_class) {
5371 MonoClass *gklass = klass->generic_class->container_class;
5373 has_finalize = mono_class_has_finalizer (gklass);
5374 } else if (klass->parent && klass->parent->has_finalize) {
5375 has_finalize = TRUE;
5377 if (klass->parent) {
5379 * Can't search in metadata for a method named Finalize, because that
5380 * ignores overrides.
5382 mono_class_setup_vtable (klass);
5383 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
5386 cmethod = klass->vtable [finalize_slot];
5390 g_assert (klass->vtable_size > finalize_slot);
5392 if (klass->parent) {
5393 if (cmethod->is_inflated)
5394 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5395 if (cmethod != default_finalize)
5396 has_finalize = TRUE;
5402 mono_image_lock (klass->image);
5404 if (!klass->has_finalize_inited) {
5405 klass->has_finalize = has_finalize ? 1 : 0;
5407 mono_memory_barrier ();
5408 klass->has_finalize_inited = TRUE;
5411 mono_image_unlock (klass->image);
5413 return klass->has_finalize;
5417 mono_is_corlib_image (MonoImage *image)
5419 /* FIXME: allow the dynamic case for our compilers and with full trust */
5420 if (image_is_dynamic (image))
5421 return image->assembly && !strcmp (image->assembly->aname.name, "mscorlib");
5423 return image == mono_defaults.corlib;
5427 * LOCKING: this assumes the loader lock is held
5430 mono_class_setup_mono_type (MonoClass *klass)
5432 const char *name = klass->name;
5433 const char *nspace = klass->name_space;
5434 gboolean is_corlib = mono_is_corlib_image (klass->image);
5436 klass->this_arg.byref = 1;
5437 klass->this_arg.data.klass = klass;
5438 klass->this_arg.type = MONO_TYPE_CLASS;
5439 klass->byval_arg.data.klass = klass;
5440 klass->byval_arg.type = MONO_TYPE_CLASS;
5442 if (is_corlib && !strcmp (nspace, "System")) {
5443 if (!strcmp (name, "ValueType")) {
5445 * do not set the valuetype bit for System.ValueType.
5446 * klass->valuetype = 1;
5448 klass->blittable = TRUE;
5449 } else if (!strcmp (name, "Enum")) {
5451 * do not set the valuetype bit for System.Enum.
5452 * klass->valuetype = 1;
5454 klass->valuetype = 0;
5455 klass->enumtype = 0;
5456 } else if (!strcmp (name, "Object")) {
5457 klass->byval_arg.type = MONO_TYPE_OBJECT;
5458 klass->this_arg.type = MONO_TYPE_OBJECT;
5459 } else if (!strcmp (name, "String")) {
5460 klass->byval_arg.type = MONO_TYPE_STRING;
5461 klass->this_arg.type = MONO_TYPE_STRING;
5462 } else if (!strcmp (name, "TypedReference")) {
5463 klass->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5464 klass->this_arg.type = MONO_TYPE_TYPEDBYREF;
5468 if (klass->valuetype) {
5469 int t = MONO_TYPE_VALUETYPE;
5471 if (is_corlib && !strcmp (nspace, "System")) {
5474 if (!strcmp (name, "Boolean")) {
5475 t = MONO_TYPE_BOOLEAN;
5476 } else if (!strcmp(name, "Byte")) {
5478 klass->blittable = TRUE;
5482 if (!strcmp (name, "Char")) {
5487 if (!strcmp (name, "Double")) {
5489 klass->blittable = TRUE;
5493 if (!strcmp (name, "Int32")) {
5495 klass->blittable = TRUE;
5496 } else if (!strcmp(name, "Int16")) {
5498 klass->blittable = TRUE;
5499 } else if (!strcmp(name, "Int64")) {
5501 klass->blittable = TRUE;
5502 } else if (!strcmp(name, "IntPtr")) {
5504 klass->blittable = TRUE;
5508 if (!strcmp (name, "Single")) {
5510 klass->blittable = TRUE;
5511 } else if (!strcmp(name, "SByte")) {
5513 klass->blittable = TRUE;
5517 if (!strcmp (name, "UInt32")) {
5519 klass->blittable = TRUE;
5520 } else if (!strcmp(name, "UInt16")) {
5522 klass->blittable = TRUE;
5523 } else if (!strcmp(name, "UInt64")) {
5525 klass->blittable = TRUE;
5526 } else if (!strcmp(name, "UIntPtr")) {
5528 klass->blittable = TRUE;
5532 if (!strcmp (name, "TypedReference")) {
5533 t = MONO_TYPE_TYPEDBYREF;
5534 klass->blittable = TRUE;
5538 if (!strcmp (name, "Void")) {
5546 klass->byval_arg.type = (MonoTypeEnum)t;
5547 klass->this_arg.type = (MonoTypeEnum)t;
5550 if (MONO_CLASS_IS_INTERFACE (klass))
5551 klass->interface_id = mono_get_unique_iid (klass);
5557 * COM initialization is delayed until needed.
5558 * However when a [ComImport] attribute is present on a type it will trigger
5559 * the initialization. This is not a problem unless the BCL being executed
5560 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5563 init_com_from_comimport (MonoClass *klass)
5565 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5566 if (mono_security_core_clr_enabled ()) {
5567 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5568 if (!mono_security_core_clr_determine_platform_image (klass->image)) {
5569 /* but it can not be made available for application (i.e. user code) since all COM calls
5570 * are considered native calls. In this case we fail with a TypeLoadException (just like
5571 * Silverlight 2 does */
5572 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5577 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5579 #endif /*DISABLE_COM*/
5582 * LOCKING: this assumes the loader lock is held
5585 mono_class_setup_parent (MonoClass *klass, MonoClass *parent)
5587 gboolean system_namespace;
5588 gboolean is_corlib = mono_is_corlib_image (klass->image);
5590 system_namespace = !strcmp (klass->name_space, "System") && is_corlib;
5592 /* if root of the hierarchy */
5593 if (system_namespace && !strcmp (klass->name, "Object")) {
5594 klass->parent = NULL;
5595 klass->instance_size = sizeof (MonoObject);
5598 if (!strcmp (klass->name, "<Module>")) {
5599 klass->parent = NULL;
5600 klass->instance_size = 0;
5604 if (!MONO_CLASS_IS_INTERFACE (klass)) {
5605 /* Imported COM Objects always derive from __ComObject. */
5607 if (MONO_CLASS_IS_IMPORT (klass)) {
5608 init_com_from_comimport (klass);
5609 if (parent == mono_defaults.object_class)
5610 parent = mono_class_get_com_object_class ();
5614 /* set the parent to something useful and safe, but mark the type as broken */
5615 parent = mono_defaults.object_class;
5616 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5619 klass->parent = parent;
5621 if (parent->generic_class && !parent->name) {
5623 * If the parent is a generic instance, we may get
5624 * called before it is fully initialized, especially
5625 * before it has its name.
5630 #ifndef DISABLE_REMOTING
5631 klass->marshalbyref = parent->marshalbyref;
5632 klass->contextbound = parent->contextbound;
5635 klass->delegate = parent->delegate;
5637 if (MONO_CLASS_IS_IMPORT (klass) || mono_class_is_com_object (parent))
5638 mono_class_set_is_com_object (klass);
5640 if (system_namespace) {
5641 #ifndef DISABLE_REMOTING
5642 if (klass->name [0] == 'M' && !strcmp (klass->name, "MarshalByRefObject"))
5643 klass->marshalbyref = 1;
5645 if (klass->name [0] == 'C' && !strcmp (klass->name, "ContextBoundObject"))
5646 klass->contextbound = 1;
5648 if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate"))
5649 klass->delegate = 1;
5652 if (klass->parent->enumtype || (mono_is_corlib_image (klass->parent->image) && (strcmp (klass->parent->name, "ValueType") == 0) &&
5653 (strcmp (klass->parent->name_space, "System") == 0)))
5654 klass->valuetype = 1;
5655 if (mono_is_corlib_image (klass->parent->image) && ((strcmp (klass->parent->name, "Enum") == 0) && (strcmp (klass->parent->name_space, "System") == 0))) {
5656 klass->valuetype = klass->enumtype = 1;
5658 /*klass->enumtype = klass->parent->enumtype; */
5660 /* initialize com types if COM interfaces are present */
5662 if (MONO_CLASS_IS_IMPORT (klass))
5663 init_com_from_comimport (klass);
5665 klass->parent = NULL;
5671 * mono_class_setup_supertypes:
5674 * Build the data structure needed to make fast type checks work.
5675 * This currently sets two fields in @class:
5676 * - idepth: distance between @class and System.Object in the type
5678 * - supertypes: array of classes: each element has a class in the hierarchy
5679 * starting from @class up to System.Object
5681 * LOCKING: This function is atomic, in case of contention we waste memory.
5684 mono_class_setup_supertypes (MonoClass *klass)
5687 MonoClass **supertypes;
5689 mono_atomic_load_acquire (supertypes, MonoClass **, &klass->supertypes);
5693 if (klass->parent && !klass->parent->supertypes)
5694 mono_class_setup_supertypes (klass->parent);
5696 klass->idepth = klass->parent->idepth + 1;
5700 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, klass->idepth);
5701 supertypes = (MonoClass **)mono_class_alloc0 (klass, sizeof (MonoClass *) * ms);
5703 if (klass->parent) {
5704 CHECKED_METADATA_WRITE_PTR ( supertypes [klass->idepth - 1] , klass );
5707 for (supertype_idx = 0; supertype_idx < klass->parent->idepth; supertype_idx++)
5708 CHECKED_METADATA_WRITE_PTR ( supertypes [supertype_idx] , klass->parent->supertypes [supertype_idx] );
5710 CHECKED_METADATA_WRITE_PTR ( supertypes [0] , klass );
5713 CHECKED_METADATA_WRITE_PTR_ATOMIC ( klass->supertypes , supertypes );
5717 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5719 MonoClass *gtd = (MonoClass*)user_data;
5720 /* Only try to fix generic instances of @gtd */
5721 if (gclass->generic_class->container_class != gtd)
5724 /* Check if the generic instance has no parent. */
5725 if (gtd->parent && !gclass->parent)
5726 mono_generic_class_setup_parent (gclass, gtd);
5732 mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char *msg)
5734 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (msg));
5735 mono_error_set_type_load_class (error, klass, msg);
5739 * mono_class_create_from_typedef:
5740 * @image: image where the token is valid
5741 * @type_token: typedef token
5742 * @error: used to return any error found while creating the type
5744 * Create the MonoClass* representing the specified type token.
5745 * @type_token must be a TypeDef token.
5747 * FIXME: don't return NULL on failure, just the the caller figure it out.
5750 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5752 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5753 MonoClass *klass, *parent = NULL;
5754 guint32 cols [MONO_TYPEDEF_SIZE];
5755 guint32 cols_next [MONO_TYPEDEF_SIZE];
5756 guint tidx = mono_metadata_token_index (type_token);
5757 MonoGenericContext *context = NULL;
5758 const char *name, *nspace;
5760 MonoClass **interfaces;
5761 guint32 field_last, method_last;
5762 guint32 nesting_tokeen;
5764 mono_error_init (error);
5766 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5767 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5768 mono_loader_assert_no_error ();
5772 mono_loader_lock ();
5774 if ((klass = (MonoClass *)mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5775 mono_loader_unlock ();
5776 mono_loader_assert_no_error ();
5780 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5782 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5783 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5785 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
5788 klass->name_space = nspace;
5790 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5792 klass->image = image;
5793 klass->type_token = type_token;
5794 klass->flags = cols [MONO_TYPEDEF_FLAGS];
5796 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
5798 classes_size += sizeof (MonoClass);
5801 * Check whether we're a generic type definition.
5803 klass->generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
5804 if (klass->generic_container) {
5805 klass->is_generic = 1;
5806 klass->generic_container->owner.klass = klass;
5807 klass->generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
5808 context = &klass->generic_container->context;
5811 if (klass->generic_container)
5812 enable_gclass_recording ();
5814 if (cols [MONO_TYPEDEF_EXTENDS]) {
5816 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5818 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5819 /*WARNING: this must satisfy mono_metadata_type_hash*/
5820 klass->this_arg.byref = 1;
5821 klass->this_arg.data.klass = klass;
5822 klass->this_arg.type = MONO_TYPE_CLASS;
5823 klass->byval_arg.data.klass = klass;
5824 klass->byval_arg.type = MONO_TYPE_CLASS;
5826 parent = mono_class_get_checked (image, parent_token, error);
5827 if (parent && context) /* Always inflate */
5828 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5830 if (parent == NULL) {
5831 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5832 goto parent_failure;
5835 for (tmp = parent; tmp; tmp = tmp->parent) {
5837 mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
5838 goto parent_failure;
5840 if (klass->generic_container && tmp->generic_class && tmp->generic_class->container_class == klass) {
5841 mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
5842 goto parent_failure;
5847 mono_class_setup_parent (klass, parent);
5849 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5850 mono_class_setup_mono_type (klass);
5852 if (klass->generic_container)
5853 disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
5856 * This might access klass->byval_arg for recursion generated by generic constraints,
5857 * so it has to come after setup_mono_type ().
5859 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5860 klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5861 if (!mono_error_ok (error)) {
5862 /*FIXME implement a mono_class_set_failure_from_mono_error */
5863 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5864 mono_loader_unlock ();
5865 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5866 mono_loader_assert_no_error ();
5871 if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5875 if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5879 klass->cast_class = klass->element_class = klass;
5881 if (!klass->enumtype) {
5882 if (!mono_metadata_interfaces_from_typedef_full (
5883 image, type_token, &interfaces, &icount, FALSE, context, error)){
5885 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5886 mono_loader_unlock ();
5887 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5891 klass->interfaces = interfaces;
5892 klass->interface_count = icount;
5893 klass->interfaces_inited = 1;
5896 /*g_print ("Load class %s\n", name);*/
5899 * Compute the field and method lists
5901 klass->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5902 klass->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5904 if (tt->rows > tidx){
5905 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5906 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5907 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5909 field_last = image->tables [MONO_TABLE_FIELD].rows;
5910 method_last = image->tables [MONO_TABLE_METHOD].rows;
5913 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5914 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5915 klass->field.count = field_last - klass->field.first;
5917 klass->field.count = 0;
5919 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5920 klass->method.count = method_last - klass->method.first;
5922 klass->method.count = 0;
5924 /* reserve space to store vector pointer in arrays */
5925 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5926 klass->instance_size += 2 * sizeof (gpointer);
5927 g_assert (klass->field.count == 0);
5930 if (klass->enumtype) {
5931 MonoType *enum_basetype = mono_class_find_enum_basetype (klass, error);
5932 if (!enum_basetype) {
5933 /*set it to a default value as the whole runtime can't handle this to be null*/
5934 klass->cast_class = klass->element_class = mono_defaults.int32_class;
5935 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5936 mono_loader_unlock ();
5937 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5938 mono_loader_assert_no_error ();
5941 klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
5945 * If we're a generic type definition, load the constraints.
5946 * We must do this after the class has been constructed to make certain recursive scenarios
5949 if (klass->generic_container && !mono_metadata_load_generic_param_constraints_checked (image, type_token, klass->generic_container, error)) {
5950 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)));
5951 mono_loader_unlock ();
5952 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5953 mono_loader_assert_no_error ();
5957 if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5958 if (!strncmp (name, "Vector", 6))
5959 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");
5962 mono_loader_unlock ();
5964 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5965 mono_loader_assert_no_error ();
5970 mono_class_setup_mono_type (klass);
5971 mono_loader_unlock ();
5972 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5973 mono_loader_assert_no_error ();
5977 /** Is klass a Nullable<T> ginst? */
5979 mono_class_is_nullable (MonoClass *klass)
5981 return klass->generic_class != NULL &&
5982 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5986 /** if klass is T? return T */
5988 mono_class_get_nullable_param (MonoClass *klass)
5990 g_assert (mono_class_is_nullable (klass));
5991 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5995 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5999 MonoGenericClass *gclass = klass->generic_class;
6001 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
6002 if (!mono_error_ok (&error)) {
6003 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
6004 klass->parent = mono_defaults.object_class;
6005 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
6006 mono_error_cleanup (&error);
6010 mono_class_setup_parent (klass, klass->parent);
6012 if (klass->enumtype) {
6013 klass->cast_class = gtd->cast_class;
6014 klass->element_class = gtd->element_class;
6020 * Create the `MonoClass' for an instantiation of a generic type.
6021 * We only do this if we actually need it.
6024 mono_generic_class_get_class (MonoGenericClass *gclass)
6026 MonoClass *klass, *gklass;
6028 if (gclass->cached_class)
6029 return gclass->cached_class;
6031 mono_loader_lock ();
6032 if (gclass->cached_class) {
6033 mono_loader_unlock ();
6034 return gclass->cached_class;
6037 klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
6039 gklass = gclass->container_class;
6041 if (record_gclass_instantiation > 0)
6042 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
6044 if (gklass->nested_in) {
6045 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
6046 klass->nested_in = gklass->nested_in;
6049 klass->name = gklass->name;
6050 klass->name_space = gklass->name_space;
6052 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6054 klass->image = gklass->image;
6055 klass->flags = gklass->flags;
6056 klass->type_token = gklass->type_token;
6057 klass->field.count = gklass->field.count;
6059 klass->is_inflated = 1;
6060 klass->generic_class = gclass;
6062 klass->byval_arg.type = MONO_TYPE_GENERICINST;
6063 klass->this_arg.type = klass->byval_arg.type;
6064 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
6065 klass->this_arg.byref = TRUE;
6066 klass->enumtype = gklass->enumtype;
6067 klass->valuetype = gklass->valuetype;
6069 klass->cast_class = klass->element_class = klass;
6071 if (mono_class_is_nullable (klass))
6072 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
6075 * We're not interested in the nested classes of a generic instance.
6076 * We use the generic type definition to look for nested classes.
6079 mono_generic_class_setup_parent (klass, gklass);
6081 if (gclass->is_dynamic) {
6083 * 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.
6084 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
6085 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
6087 if (!gklass->wastypebuilder)
6090 mono_class_setup_supertypes (klass);
6092 if (klass->enumtype) {
6094 * For enums, gklass->fields might not been set, but instance_size etc. is
6095 * already set in mono_reflection_create_internal_class (). For non-enums,
6096 * these will be computed normally in mono_class_layout_fields ().
6098 klass->instance_size = gklass->instance_size;
6099 klass->sizes.class_size = gklass->sizes.class_size;
6100 mono_memory_barrier ();
6101 klass->size_inited = 1;
6105 mono_memory_barrier ();
6106 gclass->cached_class = klass;
6108 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6110 inflated_classes ++;
6111 inflated_classes_size += sizeof (MonoClass);
6113 mono_loader_unlock ();
6119 get_image_for_container (MonoGenericContainer *container)
6122 if (container->is_anonymous) {
6123 result = container->owner.image;
6126 if (container->is_method) {
6127 MonoMethod *method = container->owner.method;
6128 g_assert_checked (method);
6129 klass = method->klass;
6131 klass = container->owner.klass;
6133 g_assert_checked (klass);
6134 result = klass->image;
6141 get_image_for_generic_param (MonoGenericParam *param)
6143 MonoGenericContainer *container = mono_generic_param_owner (param);
6144 g_assert_checked (container);
6145 return get_image_for_container (container);
6148 // Make a string in the designated image consisting of a single integer.
6149 #define INT_STRING_SIZE 16
6151 make_generic_name_string (MonoImage *image, int num)
6153 char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
6154 g_snprintf (name, INT_STRING_SIZE, "%d", num);
6158 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
6159 // pinfo is derived from param by the caller for us.
6161 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
6163 MonoClass *klass, **ptr;
6165 MonoGenericContainer *container = mono_generic_param_owner (param);
6166 g_assert_checked (container);
6168 MonoImage *image = get_image_for_container (container);
6169 gboolean is_mvar = container->is_method;
6170 gboolean is_anonymous = container->is_anonymous;
6172 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6173 classes_size += sizeof (MonoClass);
6176 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
6178 int n = mono_generic_param_num (param);
6179 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
6183 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , "" );
6184 } else if (is_mvar) {
6185 MonoMethod *omethod = container->owner.method;
6186 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
6188 MonoClass *oklass = container->owner.klass;
6189 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
6192 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6194 // Count non-NULL items in pinfo->constraints
6197 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6201 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6202 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
6204 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
6205 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
6207 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
6210 if (count - pos > 0) {
6211 klass->interface_count = count - pos;
6212 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
6213 klass->interfaces_inited = TRUE;
6214 for (i = pos; i < count; i++)
6215 CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
6218 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
6220 klass->inited = TRUE;
6221 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class , klass );
6222 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
6223 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
6225 klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6226 klass->this_arg.type = klass->byval_arg.type;
6227 CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param , param );
6228 CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
6229 klass->this_arg.byref = TRUE;
6231 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6232 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6234 /*Init these fields to sane values*/
6235 klass->min_align = 1;
6237 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6238 * constrained to, the JIT depends on this.
6240 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6241 mono_memory_barrier ();
6242 klass->size_inited = 1;
6243 klass->setup_fields_called = 1;
6245 mono_class_setup_supertypes (klass);
6247 if (count - pos > 0) {
6248 mono_class_setup_vtable (klass->parent);
6249 if (mono_class_has_failure (klass->parent))
6250 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
6252 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6258 #define FAST_CACHE_SIZE 16
6261 * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6262 * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6263 * we cache the MonoClasses.
6264 * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6265 * LOCKING: Takes the image lock depending on @take_lock.
6268 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6270 int n = mono_generic_param_num (param);
6271 MonoImage *image = get_image_for_generic_param (param);
6272 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6273 MonoClass *klass = NULL;
6278 // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6279 // For high numbers or constraints we have to use pointer hashes.
6280 if (param->gshared_constraint) {
6281 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6284 mono_image_lock (image);
6285 klass = (MonoClass *)g_hash_table_lookup (ht, param);
6287 mono_image_unlock (image);
6292 if (n < FAST_CACHE_SIZE) {
6294 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6296 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6298 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6301 mono_image_lock (image);
6302 klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6304 mono_image_unlock (image);
6311 * LOCKING: Image lock (param->image) must be held
6314 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6316 int n = mono_generic_param_num (param);
6317 MonoImage *image = get_image_for_generic_param (param);
6318 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6322 if (param->gshared_constraint) {
6323 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6325 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6326 mono_memory_barrier ();
6328 image->mvar_cache_constrained = ht;
6330 image->var_cache_constrained = ht;
6332 g_hash_table_insert (ht, param, klass);
6333 } else if (n < FAST_CACHE_SIZE) {
6335 /* Requires locking to avoid droping an already published class */
6336 if (!image->mvar_cache_fast)
6337 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6338 image->mvar_cache_fast [n] = klass;
6340 if (!image->var_cache_fast)
6341 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6342 image->var_cache_fast [n] = klass;
6345 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6347 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6349 ht = g_hash_table_new (NULL, NULL);
6350 mono_memory_barrier ();
6352 image->mvar_cache_slow = ht;
6354 image->var_cache_slow = ht;
6357 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6362 * LOCKING: Acquires the image lock (@image).
6365 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6367 MonoImage *image = get_image_for_generic_param (param);
6368 MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6369 MonoClass *klass, *klass2;
6371 // If a klass already exists for this object and is cached, return it.
6372 if (pinfo) // Non-anonymous
6373 klass = pinfo->pklass;
6375 klass = get_anon_gparam_class (param, TRUE);
6380 // Create a new klass
6381 klass = make_generic_param_class (param, pinfo);
6383 // Now we need to cache the klass we created.
6384 // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6385 // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6386 // and allow our newly-created klass object to just leak.
6387 mono_memory_barrier ();
6389 mono_image_lock (image);
6391 // Here "klass2" refers to the klass potentially created by the other thread.
6392 if (pinfo) // Repeat check from above
6393 klass2 = pinfo->pklass;
6395 klass2 = get_anon_gparam_class (param, FALSE);
6402 pinfo->pklass = klass;
6404 set_anon_gparam_class (param, klass);
6406 mono_image_unlock (image);
6408 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6410 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED); // Alert profiler about botched class create
6412 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6418 * mono_class_from_generic_parameter:
6419 * @param: Parameter to find/construct a class for.
6420 * @arg2: Is ignored.
6421 * @arg3: Is ignored.
6424 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6426 return mono_class_from_generic_parameter_internal (param);
6431 mono_ptr_class_get (MonoType *type)
6434 MonoClass *el_class;
6438 el_class = mono_class_from_mono_type (type);
6439 image = el_class->image;
6441 mono_image_lock (image);
6442 if (image->ptr_cache) {
6443 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6444 mono_image_unlock (image);
6448 mono_image_unlock (image);
6450 result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6452 classes_size += sizeof (MonoClass);
6454 result->parent = NULL; /* no parent for PTR types */
6455 result->name_space = el_class->name_space;
6456 name = g_strdup_printf ("%s*", el_class->name);
6457 result->name = mono_image_strdup (image, name);
6460 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6462 result->image = el_class->image;
6463 result->inited = TRUE;
6464 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6465 /* Can pointers get boxed? */
6466 result->instance_size = sizeof (gpointer);
6467 result->cast_class = result->element_class = el_class;
6468 result->blittable = TRUE;
6470 result->byval_arg.type = MONO_TYPE_PTR;
6471 result->this_arg.type = result->byval_arg.type;
6472 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6473 result->this_arg.byref = TRUE;
6475 mono_class_setup_supertypes (result);
6477 mono_image_lock (image);
6478 if (image->ptr_cache) {
6480 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6481 mono_image_unlock (image);
6482 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6486 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6488 g_hash_table_insert (image->ptr_cache, el_class, result);
6489 mono_image_unlock (image);
6491 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6497 mono_fnptr_class_get (MonoMethodSignature *sig)
6500 static GHashTable *ptr_hash = NULL;
6502 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6504 mono_loader_lock ();
6507 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6509 if ((result = (MonoClass *)g_hash_table_lookup (ptr_hash, sig))) {
6510 mono_loader_unlock ();
6513 result = g_new0 (MonoClass, 1);
6515 result->parent = NULL; /* no parent for PTR types */
6516 result->name_space = "System";
6517 result->name = "MonoFNPtrFakeClass";
6519 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6521 result->image = mono_defaults.corlib; /* need to fix... */
6522 result->inited = TRUE;
6523 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6524 /* Can pointers get boxed? */
6525 result->instance_size = sizeof (gpointer);
6526 result->cast_class = result->element_class = result;
6527 result->blittable = TRUE;
6529 result->byval_arg.type = MONO_TYPE_FNPTR;
6530 result->this_arg.type = result->byval_arg.type;
6531 result->this_arg.data.method = result->byval_arg.data.method = sig;
6532 result->this_arg.byref = TRUE;
6533 result->blittable = TRUE;
6535 mono_class_setup_supertypes (result);
6537 g_hash_table_insert (ptr_hash, sig, result);
6539 mono_loader_unlock ();
6541 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6547 * mono_class_from_mono_type:
6548 * @type: describes the type to return
6550 * This returns a MonoClass for the specified MonoType, the value is never NULL.
6553 mono_class_from_mono_type (MonoType *type)
6555 switch (type->type) {
6556 case MONO_TYPE_OBJECT:
6557 return type->data.klass? type->data.klass: mono_defaults.object_class;
6558 case MONO_TYPE_VOID:
6559 return type->data.klass? type->data.klass: mono_defaults.void_class;
6560 case MONO_TYPE_BOOLEAN:
6561 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6562 case MONO_TYPE_CHAR:
6563 return type->data.klass? type->data.klass: mono_defaults.char_class;
6565 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6567 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6569 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6571 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6573 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6575 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6577 return type->data.klass? type->data.klass: mono_defaults.int_class;
6579 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6581 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6583 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6585 return type->data.klass? type->data.klass: mono_defaults.single_class;
6587 return type->data.klass? type->data.klass: mono_defaults.double_class;
6588 case MONO_TYPE_STRING:
6589 return type->data.klass? type->data.klass: mono_defaults.string_class;
6590 case MONO_TYPE_TYPEDBYREF:
6591 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6592 case MONO_TYPE_ARRAY:
6593 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6595 return mono_ptr_class_get (type->data.type);
6596 case MONO_TYPE_FNPTR:
6597 return mono_fnptr_class_get (type->data.method);
6598 case MONO_TYPE_SZARRAY:
6599 return mono_array_class_get (type->data.klass, 1);
6600 case MONO_TYPE_CLASS:
6601 case MONO_TYPE_VALUETYPE:
6602 return type->data.klass;
6603 case MONO_TYPE_GENERICINST:
6604 return mono_generic_class_get_class (type->data.generic_class);
6605 case MONO_TYPE_MVAR:
6607 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6609 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6610 g_assert_not_reached ();
6613 // Yes, this returns NULL, even if it is documented as not doing so, but there
6614 // is no way for the code to make it this far, due to the assert above.
6619 * mono_type_retrieve_from_typespec
6620 * @image: context where the image is created
6621 * @type_spec: typespec token
6622 * @context: the generic context used to evaluate generic instantiations in
6625 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6627 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6629 *did_inflate = FALSE;
6634 if (context && (context->class_inst || context->method_inst)) {
6635 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6637 if (!mono_error_ok (error)) {
6638 mono_loader_assert_no_error ();
6644 *did_inflate = TRUE;
6651 * mono_class_create_from_typespec
6652 * @image: context where the image is created
6653 * @type_spec: typespec token
6654 * @context: the generic context used to evaluate generic instantiations in
6657 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6660 gboolean inflated = FALSE;
6661 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6662 return_val_if_nok (error, NULL);
6663 ret = mono_class_from_mono_type (t);
6665 mono_metadata_free_type (t);
6670 * mono_bounded_array_class_get:
6671 * @element_class: element class
6672 * @rank: the dimension of the array class
6673 * @bounded: whenever the array has non-zero bounds
6675 * Returns: A class object describing the array with element type @element_type and
6679 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6683 MonoClass *parent = NULL;
6684 GSList *list, *rootlist = NULL;
6687 gboolean corlib_type = FALSE;
6689 g_assert (rank <= 255);
6692 /* bounded only matters for one-dimensional arrays */
6695 image = eclass->image;
6697 if (rank == 1 && !bounded) {
6699 * This case is very frequent not just during compilation because of calls
6700 * from mono_class_from_mono_type (), mono_array_new (),
6701 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6703 mono_os_mutex_lock (&image->szarray_cache_lock);
6704 if (!image->szarray_cache)
6705 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6706 klass = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6707 mono_os_mutex_unlock (&image->szarray_cache_lock);
6711 mono_loader_lock ();
6713 mono_loader_lock ();
6715 if (!image->array_cache)
6716 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6718 if ((rootlist = list = (GSList *)g_hash_table_lookup (image->array_cache, eclass))) {
6719 for (; list; list = list->next) {
6720 klass = (MonoClass *)list->data;
6721 if ((klass->rank == rank) && (klass->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6722 mono_loader_unlock ();
6729 /* for the building corlib use System.Array from it */
6730 if (image->assembly && assembly_is_dynamic (image->assembly) && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6731 parent = mono_class_load_from_name (image, "System", "Array");
6734 parent = mono_defaults.array_class;
6735 if (!parent->inited)
6736 mono_class_init (parent);
6739 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6741 klass->image = image;
6742 klass->name_space = eclass->name_space;
6743 nsize = strlen (eclass->name);
6744 name = (char *)g_malloc (nsize + 2 + rank + 1);
6745 memcpy (name, eclass->name, nsize);
6748 memset (name + nsize + 1, ',', rank - 1);
6750 name [nsize + rank] = '*';
6751 name [nsize + rank + bounded] = ']';
6752 name [nsize + rank + bounded + 1] = 0;
6753 klass->name = mono_image_strdup (image, name);
6756 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6758 classes_size += sizeof (MonoClass);
6760 klass->type_token = 0;
6761 /* all arrays are marked serializable and sealed, bug #42779 */
6762 klass->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6763 klass->parent = parent;
6764 klass->instance_size = mono_class_instance_size (klass->parent);
6766 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6767 /*Arrays of those two types are invalid.*/
6768 mono_class_set_failure (klass, MONO_EXCEPTION_INVALID_PROGRAM, NULL);
6769 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6770 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6771 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6772 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6774 /* element_size -1 is ok as this is not an instantitable type*/
6775 klass->sizes.element_size = -1;
6777 klass->sizes.element_size = mono_class_array_element_size (eclass);
6779 mono_class_setup_supertypes (klass);
6781 if (eclass->generic_class)
6782 mono_class_init (eclass);
6783 if (!eclass->size_inited)
6784 mono_class_setup_fields (eclass);
6785 if (mono_class_has_failure (eclass)) /*FIXME we fail the array type, but we have to let other fields be set.*/
6786 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
6788 klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6792 if (eclass->enumtype)
6793 klass->cast_class = eclass->element_class;
6795 klass->cast_class = eclass;
6797 switch (klass->cast_class->byval_arg.type) {
6799 klass->cast_class = mono_defaults.byte_class;
6802 klass->cast_class = mono_defaults.int16_class;
6805 #if SIZEOF_VOID_P == 4
6809 klass->cast_class = mono_defaults.int32_class;
6812 #if SIZEOF_VOID_P == 8
6816 klass->cast_class = mono_defaults.int64_class;
6822 klass->element_class = eclass;
6824 if ((rank > 1) || bounded) {
6825 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6826 klass->byval_arg.type = MONO_TYPE_ARRAY;
6827 klass->byval_arg.data.array = at;
6828 at->eklass = eclass;
6830 /* FIXME: complete.... */
6832 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6833 klass->byval_arg.data.klass = eclass;
6835 klass->this_arg = klass->byval_arg;
6836 klass->this_arg.byref = 1;
6841 klass->generic_container = eclass->generic_container;
6843 if (rank == 1 && !bounded) {
6844 MonoClass *prev_class;
6846 mono_os_mutex_lock (&image->szarray_cache_lock);
6847 prev_class = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6849 /* Someone got in before us */
6852 g_hash_table_insert (image->szarray_cache, eclass, klass);
6853 mono_os_mutex_unlock (&image->szarray_cache_lock);
6855 list = g_slist_append (rootlist, klass);
6856 g_hash_table_insert (image->array_cache, eclass, list);
6859 mono_loader_unlock ();
6861 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6867 * mono_array_class_get:
6868 * @element_class: element class
6869 * @rank: the dimension of the array class
6871 * Returns: A class object describing the array with element type @element_type and
6875 mono_array_class_get (MonoClass *eclass, guint32 rank)
6877 return mono_bounded_array_class_get (eclass, rank, FALSE);
6881 * mono_class_instance_size:
6884 * Use to get the size of a class in bytes.
6886 * Returns: The size of an object instance
6889 mono_class_instance_size (MonoClass *klass)
6891 if (!klass->size_inited)
6892 mono_class_init (klass);
6894 return klass->instance_size;
6898 * mono_class_min_align:
6901 * Use to get the computed minimum alignment requirements for the specified class.
6903 * Returns: minimm alignment requirements
6906 mono_class_min_align (MonoClass *klass)
6908 if (!klass->size_inited)
6909 mono_class_init (klass);
6911 return klass->min_align;
6915 * mono_class_value_size:
6918 * This function is used for value types, and return the
6919 * space and the alignment to store that kind of value object.
6921 * Returns: the size of a value of kind @klass
6924 mono_class_value_size (MonoClass *klass, guint32 *align)
6928 /* fixme: check disable, because we still have external revereces to
6929 * mscorlib and Dummy Objects
6931 /*g_assert (klass->valuetype);*/
6933 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6936 *align = klass->min_align;
6942 * mono_class_data_size:
6945 * Returns: The size of the static class data
6948 mono_class_data_size (MonoClass *klass)
6951 mono_class_init (klass);
6952 /* This can happen with dynamically created types */
6953 if (!klass->fields_inited)
6954 mono_class_setup_fields_locking (klass);
6956 /* in arrays, sizes.class_size is unioned with element_size
6957 * and arrays have no static fields
6961 return klass->sizes.class_size;
6965 * Auxiliary routine to mono_class_get_field
6967 * Takes a field index instead of a field token.
6969 static MonoClassField *
6970 mono_class_get_field_idx (MonoClass *klass, int idx)
6972 mono_class_setup_fields_locking (klass);
6973 if (mono_class_has_failure (klass))
6977 if (klass->image->uncompressed_metadata) {
6979 * klass->field.first points to the FieldPtr table, while idx points into the
6980 * Field table, so we have to do a search.
6982 /*FIXME this is broken for types with multiple fields with the same name.*/
6983 const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6986 for (i = 0; i < klass->field.count; ++i)
6987 if (mono_field_get_name (&klass->fields [i]) == name)
6988 return &klass->fields [i];
6989 g_assert_not_reached ();
6991 if (klass->field.count) {
6992 if ((idx >= klass->field.first) && (idx < klass->field.first + klass->field.count)){
6993 return &klass->fields [idx - klass->field.first];
6997 klass = klass->parent;
7003 * mono_class_get_field:
7004 * @class: the class to lookup the field.
7005 * @field_token: the field token
7007 * Returns: A MonoClassField representing the type and offset of
7008 * the field, or a NULL value if the field does not belong to this
7012 mono_class_get_field (MonoClass *klass, guint32 field_token)
7014 int idx = mono_metadata_token_index (field_token);
7016 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
7018 return mono_class_get_field_idx (klass, idx - 1);
7022 * mono_class_get_field_from_name:
7023 * @klass: the class to lookup the field.
7024 * @name: the field name
7026 * Search the class @klass and it's parents for a field with the name @name.
7028 * Returns: The MonoClassField pointer of the named field or NULL
7031 mono_class_get_field_from_name (MonoClass *klass, const char *name)
7033 return mono_class_get_field_from_name_full (klass, name, NULL);
7037 * mono_class_get_field_from_name_full:
7038 * @klass: the class to lookup the field.
7039 * @name: the field name
7040 * @type: the type of the fields. This optional.
7042 * Search the class @klass and it's parents for a field with the name @name and type @type.
7044 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
7045 * of its generic type definition.
7047 * Returns: The MonoClassField pointer of the named field or NULL
7050 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
7054 mono_class_setup_fields_locking (klass);
7055 if (mono_class_has_failure (klass))
7059 for (i = 0; i < klass->field.count; ++i) {
7060 MonoClassField *field = &klass->fields [i];
7062 if (strcmp (name, mono_field_get_name (field)) != 0)
7066 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
7067 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
7072 klass = klass->parent;
7078 * mono_class_get_field_token:
7079 * @field: the field we need the token of
7081 * Get the token of a field. Note that the tokesn is only valid for the image
7082 * the field was loaded from. Don't use this function for fields in dynamic types.
7084 * Returns: The token representing the field in the image it was loaded from.
7087 mono_class_get_field_token (MonoClassField *field)
7089 MonoClass *klass = field->parent;
7092 mono_class_setup_fields_locking (klass);
7097 for (i = 0; i < klass->field.count; ++i) {
7098 if (&klass->fields [i] == field) {
7099 int idx = klass->field.first + i + 1;
7101 if (klass->image->uncompressed_metadata)
7102 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
7103 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
7106 klass = klass->parent;
7109 g_assert_not_reached ();
7114 mono_field_get_index (MonoClassField *field)
7116 int index = field - field->parent->fields;
7118 g_assert (index >= 0 && index < field->parent->field.count);
7124 * mono_class_get_field_default_value:
7126 * Return the default value of the field as a pointer into the metadata blob.
7129 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
7132 guint32 constant_cols [MONO_CONSTANT_SIZE];
7134 MonoClass *klass = field->parent;
7136 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7138 if (!klass->ext || !klass->ext->field_def_values) {
7139 MonoFieldDefaultValue *def_values;
7141 mono_class_alloc_ext (klass);
7143 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
7145 mono_image_lock (klass->image);
7146 mono_memory_barrier ();
7147 if (!klass->ext->field_def_values)
7148 klass->ext->field_def_values = def_values;
7149 mono_image_unlock (klass->image);
7152 field_index = mono_field_get_index (field);
7154 if (!klass->ext->field_def_values [field_index].data) {
7155 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7159 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7161 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7162 klass->ext->field_def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7163 klass->ext->field_def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7166 *def_type = klass->ext->field_def_values [field_index].def_type;
7167 return klass->ext->field_def_values [field_index].data;
7171 mono_property_get_index (MonoProperty *prop)
7173 int index = prop - prop->parent->ext->properties;
7175 g_assert (index >= 0 && index < prop->parent->ext->property.count);
7181 * mono_class_get_property_default_value:
7183 * Return the default value of the field as a pointer into the metadata blob.
7186 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7189 guint32 constant_cols [MONO_CONSTANT_SIZE];
7190 MonoClass *klass = property->parent;
7192 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7194 * We don't cache here because it is not used by C# so it's quite rare, but
7195 * we still do the lookup in klass->ext because that is where the data
7196 * is stored for dynamic assemblies.
7199 if (image_is_dynamic (klass->image)) {
7200 int prop_index = mono_property_get_index (property);
7201 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
7202 *def_type = klass->ext->prop_def_values [prop_index].def_type;
7203 return klass->ext->prop_def_values [prop_index].data;
7207 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7211 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7212 *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7213 return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7217 mono_class_get_event_token (MonoEvent *event)
7219 MonoClass *klass = event->parent;
7224 for (i = 0; i < klass->ext->event.count; ++i) {
7225 if (&klass->ext->events [i] == event)
7226 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
7229 klass = klass->parent;
7232 g_assert_not_reached ();
7237 * mono_class_get_property_from_name:
7239 * @name: name of the property to lookup in the specified class
7241 * Use this method to lookup a property in a class
7242 * Returns: the MonoProperty with the given name, or NULL if the property
7243 * does not exist on the @klass.
7246 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7250 gpointer iter = NULL;
7251 while ((p = mono_class_get_properties (klass, &iter))) {
7252 if (! strcmp (name, p->name))
7255 klass = klass->parent;
7261 * mono_class_get_property_token:
7262 * @prop: MonoProperty to query
7264 * Returns: The ECMA token for the specified property.
7267 mono_class_get_property_token (MonoProperty *prop)
7269 MonoClass *klass = prop->parent;
7273 gpointer iter = NULL;
7274 while ((p = mono_class_get_properties (klass, &iter))) {
7275 if (&klass->ext->properties [i] == prop)
7276 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
7280 klass = klass->parent;
7283 g_assert_not_reached ();
7288 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7290 const char *name, *nspace;
7291 if (image_is_dynamic (image))
7292 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7294 switch (type_token & 0xff000000){
7295 case MONO_TOKEN_TYPE_DEF: {
7296 guint32 cols [MONO_TYPEDEF_SIZE];
7297 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7298 guint tidx = mono_metadata_token_index (type_token);
7300 if (tidx > tt->rows)
7301 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7303 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7304 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7305 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7306 if (strlen (nspace) == 0)
7307 return g_strdup_printf ("%s", name);
7309 return g_strdup_printf ("%s.%s", nspace, name);
7312 case MONO_TOKEN_TYPE_REF: {
7314 guint32 cols [MONO_TYPEREF_SIZE];
7315 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7316 guint tidx = mono_metadata_token_index (type_token);
7319 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7321 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7322 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7323 mono_error_cleanup (&error);
7327 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7328 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7329 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7330 if (strlen (nspace) == 0)
7331 return g_strdup_printf ("%s", name);
7333 return g_strdup_printf ("%s.%s", nspace, name);
7336 case MONO_TOKEN_TYPE_SPEC:
7337 return g_strdup_printf ("Typespec 0x%08x", type_token);
7339 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7344 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7346 if (image_is_dynamic (image))
7347 return g_strdup_printf ("DynamicAssembly %s", image->name);
7349 switch (type_token & 0xff000000){
7350 case MONO_TOKEN_TYPE_DEF:
7351 if (image->assembly)
7352 return mono_stringify_assembly_name (&image->assembly->aname);
7353 else if (image->assembly_name)
7354 return g_strdup (image->assembly_name);
7355 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7356 case MONO_TOKEN_TYPE_REF: {
7358 MonoAssemblyName aname;
7359 guint32 cols [MONO_TYPEREF_SIZE];
7360 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7361 guint32 idx = mono_metadata_token_index (type_token);
7364 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7366 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7367 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7368 mono_error_cleanup (&error);
7371 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7373 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7374 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7375 case MONO_RESOLUTION_SCOPE_MODULE:
7377 return g_strdup ("");
7378 case MONO_RESOLUTION_SCOPE_MODULEREF:
7380 return g_strdup ("");
7381 case MONO_RESOLUTION_SCOPE_TYPEREF:
7383 return g_strdup ("");
7384 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7385 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7386 return mono_stringify_assembly_name (&aname);
7388 g_assert_not_reached ();
7392 case MONO_TOKEN_TYPE_SPEC:
7394 return g_strdup ("");
7396 g_assert_not_reached ();
7403 * mono_class_get_full:
7404 * @image: the image where the class resides
7405 * @type_token: the token for the class
7406 * @context: the generic context used to evaluate generic instantiations in
7407 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7409 * Returns: The MonoClass that represents @type_token in @image
7412 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7416 klass = mono_class_get_checked (image, type_token, &error);
7418 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7419 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7421 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7427 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7431 mono_error_init (error);
7432 klass = mono_class_get_checked (image, type_token, error);
7434 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7435 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7440 * mono_class_get_checked:
7441 * @image: the image where the class resides
7442 * @type_token: the token for the class
7443 * @error: error object to return any error
7445 * Returns: The MonoClass that represents @type_token in @image, or NULL on error.
7448 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7450 MonoClass *klass = NULL;
7452 mono_error_init (error);
7454 if (image_is_dynamic (image)) {
7455 int table = mono_metadata_token_table (type_token);
7457 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7458 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7461 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL); /*FIXME proper error handling*/
7465 switch (type_token & 0xff000000){
7466 case MONO_TOKEN_TYPE_DEF:
7467 klass = mono_class_create_from_typedef (image, type_token, error);
7469 case MONO_TOKEN_TYPE_REF:
7470 klass = mono_class_from_typeref_checked (image, type_token, error);
7472 case MONO_TOKEN_TYPE_SPEC:
7473 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7476 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7480 /* Generic case, should be avoided for when a better error is possible. */
7481 if (!klass && mono_error_ok (error)) {
7482 char *name = mono_class_name_from_token (image, type_token);
7483 char *assembly = mono_assembly_name_from_token (image, type_token);
7484 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7492 * mono_type_get_checked:
7493 * @image: the image where the type resides
7494 * @type_token: the token for the type
7495 * @context: the generic context used to evaluate generic instantiations in
7496 * @error: Error handling context
7498 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7500 * Returns: The MonoType that represents @type_token in @image
7503 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7505 MonoType *type = NULL;
7506 gboolean inflated = FALSE;
7508 mono_error_init (error);
7510 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7511 if (image_is_dynamic (image))
7512 return mono_class_get_type ((MonoClass *)mono_lookup_dynamic_token (image, type_token, context));
7514 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7515 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7518 mono_loader_assert_no_error ();
7523 return mono_class_get_type (klass);
7526 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7529 mono_loader_assert_no_error ();
7534 MonoType *tmp = type;
7535 type = mono_class_get_type (mono_class_from_mono_type (type));
7536 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7537 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7538 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7540 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7542 if (type->type != tmp->type)
7545 mono_metadata_free_type (tmp);
7552 * @image: image where the class token will be looked up.
7553 * @type_token: a type token from the image
7555 * Returns the MonoClass with the given @type_token on the @image
7558 mono_class_get (MonoImage *image, guint32 type_token)
7560 return mono_class_get_full (image, type_token, NULL);
7564 * mono_image_init_name_cache:
7566 * Initializes the class name cache stored in image->name_cache.
7568 * LOCKING: Acquires the corresponding image lock.
7571 mono_image_init_name_cache (MonoImage *image)
7573 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7574 guint32 cols [MONO_TYPEDEF_SIZE];
7577 guint32 i, visib, nspace_index;
7578 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7580 if (image->name_cache)
7583 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7585 if (image_is_dynamic (image)) {
7586 mono_image_lock (image);
7587 if (image->name_cache) {
7588 /* Somebody initialized it before us */
7589 g_hash_table_destroy (the_name_cache);
7591 mono_atomic_store_release (&image->name_cache, the_name_cache);
7593 mono_image_unlock (image);
7597 /* Temporary hash table to avoid lookups in the nspace_table */
7598 name_cache2 = g_hash_table_new (NULL, NULL);
7600 for (i = 1; i <= t->rows; ++i) {
7601 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7602 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7604 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7605 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7607 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7609 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7610 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7612 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7613 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7614 if (!nspace_table) {
7615 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7616 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7617 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7620 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7623 /* Load type names from EXPORTEDTYPES table */
7625 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7626 guint32 cols [MONO_EXP_TYPE_SIZE];
7629 for (i = 0; i < t->rows; ++i) {
7630 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7632 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7633 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7637 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7638 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7640 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7641 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7642 if (!nspace_table) {
7643 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7644 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7645 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7648 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7652 g_hash_table_destroy (name_cache2);
7654 mono_image_lock (image);
7655 if (image->name_cache) {
7656 /* Somebody initialized it before us */
7657 g_hash_table_destroy (the_name_cache);
7659 mono_atomic_store_release (&image->name_cache, the_name_cache);
7661 mono_image_unlock (image);
7664 /*FIXME Only dynamic assemblies should allow this operation.*/
7666 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7667 const char *name, guint32 index)
7669 GHashTable *nspace_table;
7670 GHashTable *name_cache;
7673 mono_image_init_name_cache (image);
7674 mono_image_lock (image);
7676 name_cache = image->name_cache;
7677 if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7678 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7679 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7682 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7683 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7685 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7687 mono_image_unlock (image);
7696 find_nocase (gpointer key, gpointer value, gpointer user_data)
7698 char *name = (char*)key;
7699 FindUserData *data = (FindUserData*)user_data;
7701 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7702 data->value = value;
7706 * mono_class_from_name_case:
7707 * @image: The MonoImage where the type is looked up in
7708 * @name_space: the type namespace
7709 * @name: the type short name.
7710 * @deprecated: use the mono_class_from_name_case_checked variant instead.
7712 * Obtains a MonoClass with a given namespace and a given name which
7713 * is located in the given MonoImage. The namespace and name
7714 * lookups are case insensitive.
7717 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7720 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7721 mono_error_cleanup (&error);
7727 * mono_class_from_name_case:
7728 * @image: The MonoImage where the type is looked up in
7729 * @name_space: the type namespace
7730 * @name: the type short name.
7733 * Obtains a MonoClass with a given namespace and a given name which
7734 * is located in the given MonoImage. The namespace and name
7735 * lookups are case insensitive.
7737 * Returns: The MonoClass if the given namespace and name were found, or NULL if it
7738 * was not found. The @error object will contain information about the problem
7742 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7744 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7745 guint32 cols [MONO_TYPEDEF_SIZE];
7750 mono_error_init (error);
7752 if (image_is_dynamic (image)) {
7754 FindUserData user_data;
7756 mono_image_init_name_cache (image);
7757 mono_image_lock (image);
7759 user_data.key = name_space;
7760 user_data.value = NULL;
7761 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7763 if (user_data.value) {
7764 GHashTable *nspace_table = (GHashTable*)user_data.value;
7766 user_data.key = name;
7767 user_data.value = NULL;
7769 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7771 if (user_data.value)
7772 token = GPOINTER_TO_UINT (user_data.value);
7775 mono_image_unlock (image);
7778 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7784 /* add a cache if needed */
7785 for (i = 1; i <= t->rows; ++i) {
7786 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7787 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7789 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7790 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7792 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7794 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7795 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7796 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7797 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7803 return_nested_in (MonoClass *klass, char *nested)
7806 char *s = strchr (nested, '/');
7807 gpointer iter = NULL;
7814 while ((found = mono_class_get_nested_types (klass, &iter))) {
7815 if (strcmp (found->name, nested) == 0) {
7817 return return_nested_in (found, s);
7825 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7827 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7828 MonoImage *file_image;
7832 mono_error_init (error);
7835 * The EXPORTEDTYPES table only contains public types, so have to search the
7837 * Note: image->modules contains the contents of the MODULEREF table, while
7838 * the real module list is in the FILE table.
7840 for (i = 0; i < file_table->rows; i++) {
7841 guint32 cols [MONO_FILE_SIZE];
7842 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7843 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7846 file_image = mono_image_load_file_for_image (image, i + 1);
7848 klass = mono_class_from_name_checked (file_image, name_space, name, error);
7849 if (klass || !is_ok (error))
7858 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7860 GHashTable *nspace_table;
7861 MonoImage *loaded_image;
7868 mono_error_init (error);
7870 // Checking visited images avoids stack overflows when cyclic references exist.
7871 if (g_hash_table_lookup (visited_images, image))
7874 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7876 if ((nested = strchr (name, '/'))) {
7877 int pos = nested - name;
7878 int len = strlen (name);
7881 memcpy (buf, name, len + 1);
7883 nested = buf + pos + 1;
7887 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7888 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7889 gboolean res = get_class_from_name (image, name_space, name, &klass);
7892 klass = search_modules (image, name_space, name, error);
7897 return klass ? return_nested_in (klass, nested) : NULL;
7903 mono_image_init_name_cache (image);
7904 mono_image_lock (image);
7906 nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7909 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7911 mono_image_unlock (image);
7913 if (!token && image_is_dynamic (image) && image->modules) {
7914 /* Search modules as well */
7915 for (i = 0; i < image->module_count; ++i) {
7916 MonoImage *module = image->modules [i];
7918 klass = mono_class_from_name_checked (module, name_space, name, error);
7919 if (klass || !is_ok (error))
7925 klass = search_modules (image, name_space, name, error);
7926 if (klass || !is_ok (error))
7933 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7934 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7935 guint32 cols [MONO_EXP_TYPE_SIZE];
7938 idx = mono_metadata_token_index (token);
7940 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7942 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7943 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7944 loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
7947 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7949 return klass ? return_nested_in (klass, nested) : NULL;
7951 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7952 guint32 assembly_idx;
7954 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7956 mono_assembly_load_reference (image, assembly_idx - 1);
7957 g_assert (image->references [assembly_idx - 1]);
7958 if (image->references [assembly_idx - 1] == (gpointer)-1)
7960 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
7962 return klass ? return_nested_in (klass, nested) : NULL;
7965 g_assert_not_reached ();
7969 token = MONO_TOKEN_TYPE_DEF | token;
7971 klass = mono_class_get_checked (image, token, error);
7973 return return_nested_in (klass, nested);
7978 * mono_class_from_name_checked:
7979 * @image: The MonoImage where the type is looked up in
7980 * @name_space: the type namespace
7981 * @name: the type short name.
7983 * Obtains a MonoClass with a given namespace and a given name which
7984 * is located in the given MonoImage.
7986 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
7987 * set if the class was not found or it will return NULL and set the error if there was a loading error.
7990 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7993 GHashTable *visited_images;
7995 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7997 klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
7999 g_hash_table_destroy (visited_images);
8005 * mono_class_from_name:
8006 * @image: The MonoImage where the type is looked up in
8007 * @name_space: the type namespace
8008 * @name: the type short name.
8010 * Obtains a MonoClass with a given namespace and a given name which
8011 * is located in the given MonoImage.
8013 * To reference nested classes, use the "/" character as a separator.
8014 * For example use "Foo/Bar" to reference the class Bar that is nested
8015 * inside Foo, like this: "class Foo { class Bar {} }".
8018 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
8023 klass = mono_class_from_name_checked (image, name_space, name, &error);
8024 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
8030 * mono_class_load_from_name:
8031 * @image: The MonoImage where the type is looked up in
8032 * @name_space: the type namespace
8033 * @name: the type short name.
8035 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
8036 * This function should be used by the runtime for critical types to which there's no way to recover but crash
8037 * If they are missing. Thing of System.Object or System.String.
8040 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
8045 klass = mono_class_from_name_checked (image, name_space, name, &error);
8047 g_error ("Runtime critical type %s.%s not found", name_space, name);
8048 if (!mono_error_ok (&error))
8049 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8054 * mono_class_try_load_from_name:
8055 * @image: The MonoImage where the type is looked up in
8056 * @name_space: the type namespace
8057 * @name: the type short name.
8059 * This function tries to load a type, returning the class was found or NULL otherwise.
8060 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
8062 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
8063 * a type that we would otherwise assume to be available but was not due some error.
8067 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
8072 klass = mono_class_from_name_checked (image, name_space, name, &error);
8073 if (!mono_error_ok (&error))
8074 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8080 * mono_class_is_subclass_of:
8081 * @klass: class to probe if it is a subclass of another one
8082 * @klassc: the class we suspect is the base class
8083 * @check_interfaces: whether we should perform interface checks
8085 * This method determines whether @klass is a subclass of @klassc.
8087 * If the @check_interfaces flag is set, then if @klassc is an interface
8088 * this method return TRUE if the @klass implements the interface or
8089 * if @klass is an interface, if one of its base classes is @klass.
8091 * If @check_interfaces is false then, then if @klass is not an interface
8092 * then it returns TRUE if the @klass is a subclass of @klassc.
8094 * if @klass is an interface and @klassc is System.Object, then this function
8099 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
8100 gboolean check_interfaces)
8102 /*FIXME test for interfaces with variant generic arguments*/
8104 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
8105 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
8107 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
8110 for (i = 0; i < klass->interface_count; i ++) {
8111 MonoClass *ic = klass->interfaces [i];
8116 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
8121 * MS.NET thinks interfaces are a subclass of Object, so we think it as
8124 if (klassc == mono_defaults.object_class)
8131 mono_type_is_generic_argument (MonoType *type)
8133 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
8137 mono_class_has_variant_generic_params (MonoClass *klass)
8140 MonoGenericContainer *container;
8142 if (!klass->generic_class)
8145 container = klass->generic_class->container_class->generic_container;
8147 for (i = 0; i < container->type_argc; ++i)
8148 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8155 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8157 if (target == candidate)
8160 if (check_for_reference_conv &&
8161 mono_type_is_generic_argument (&target->byval_arg) &&
8162 mono_type_is_generic_argument (&candidate->byval_arg)) {
8163 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8164 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8166 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8169 if (!mono_class_is_assignable_from (target, candidate))
8175 * @container the generic container from the GTD
8176 * @klass: the class to be assigned to
8177 * @oklass: the source class
8179 * Both @klass and @oklass must be instances of the same generic interface.
8181 * Returns: TRUE if @klass can be assigned to a @klass variable
8184 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8187 MonoType **klass_argv, **oklass_argv;
8188 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8189 MonoGenericContainer *container = klass_gtd->generic_container;
8191 if (klass == oklass)
8194 /*Viable candidates are instances of the same generic interface*/
8195 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8198 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8199 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8201 for (j = 0; j < container->type_argc; ++j) {
8202 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8203 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8205 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8209 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8210 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8212 if (param1_class != param2_class) {
8213 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8214 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8216 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8217 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8227 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8229 MonoGenericParam *gparam, *ogparam;
8230 MonoGenericParamInfo *tinfo, *cinfo;
8231 MonoClass **candidate_class;
8232 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8235 if (target == candidate)
8237 if (target->byval_arg.type != candidate->byval_arg.type)
8240 gparam = target->byval_arg.data.generic_param;
8241 ogparam = candidate->byval_arg.data.generic_param;
8242 tinfo = mono_generic_param_info (gparam);
8243 cinfo = mono_generic_param_info (ogparam);
8245 class_constraint_satisfied = FALSE;
8246 valuetype_constraint_satisfied = FALSE;
8248 /*candidate must have a super set of target's special constraints*/
8249 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8250 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8252 if (cinfo->constraints) {
8253 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8254 MonoClass *cc = *candidate_class;
8256 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8257 class_constraint_satisfied = TRUE;
8258 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8259 valuetype_constraint_satisfied = TRUE;
8262 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8263 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8265 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8267 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8269 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8270 valuetype_constraint_satisfied)) {
8275 /*candidate type constraints must be a superset of target's*/
8276 if (tinfo->constraints) {
8277 MonoClass **target_class;
8278 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8279 MonoClass *tc = *target_class;
8282 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8283 * check it's constraints since it satisfy the constraint by itself.
8285 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8288 if (!cinfo->constraints)
8291 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8292 MonoClass *cc = *candidate_class;
8294 if (mono_class_is_assignable_from (tc, cc))
8298 * This happens when we have the following:
8300 * Bar<K> where K : IFace
8301 * Foo<T, U> where T : U where U : IFace
8303 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8306 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8307 if (mono_gparam_is_assignable_from (target, cc))
8311 if (!*candidate_class)
8316 /*candidate itself must have a constraint that satisfy target*/
8317 if (cinfo->constraints) {
8318 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8319 MonoClass *cc = *candidate_class;
8320 if (mono_class_is_assignable_from (target, cc))
8328 * mono_class_is_assignable_from:
8329 * @klass: the class to be assigned to
8330 * @oklass: the source class
8332 * Returns: TRUE if an instance of object oklass can be assigned to an
8333 * instance of object @klass
8336 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8339 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8341 mono_class_init (klass);
8343 if (!oklass->inited)
8344 mono_class_init (oklass);
8346 if (mono_class_has_failure (klass) || mono_class_has_failure (oklass))
8349 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8350 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8352 return mono_gparam_is_assignable_from (klass, oklass);
8355 if (MONO_CLASS_IS_INTERFACE (klass)) {
8356 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8357 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8358 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8362 for (i = 0; constraints [i]; ++i) {
8363 if (mono_class_is_assignable_from (klass, constraints [i]))
8371 /* interface_offsets might not be set for dynamic classes */
8372 if (oklass->ref_info_handle && !oklass->interface_bitmap) {
8374 * oklass might be a generic type parameter but they have
8375 * interface_offsets set.
8377 gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8378 if (!is_ok (&error)) {
8379 mono_error_cleanup (&error);
8384 if (!oklass->interface_bitmap)
8385 /* Happens with generic instances of not-yet created dynamic types */
8387 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8390 if (mono_class_has_variant_generic_params (klass)) {
8392 mono_class_setup_interfaces (oklass, &error);
8393 if (!mono_error_ok (&error)) {
8394 mono_error_cleanup (&error);
8398 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8399 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8400 MonoClass *iface = oklass->interfaces_packed [i];
8402 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8407 } else if (klass->delegate) {
8408 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8410 }else if (klass->rank) {
8411 MonoClass *eclass, *eoclass;
8413 if (oklass->rank != klass->rank)
8416 /* vectors vs. one dimensional arrays */
8417 if (oklass->byval_arg.type != klass->byval_arg.type)
8420 eclass = klass->cast_class;
8421 eoclass = oklass->cast_class;
8424 * a is b does not imply a[] is b[] when a is a valuetype, and
8425 * b is a reference type.
8428 if (eoclass->valuetype) {
8429 if ((eclass == mono_defaults.enum_class) ||
8430 (eclass == mono_defaults.enum_class->parent) ||
8431 (eclass == mono_defaults.object_class))
8435 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8436 } else if (mono_class_is_nullable (klass)) {
8437 if (mono_class_is_nullable (oklass))
8438 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8440 return mono_class_is_assignable_from (klass->cast_class, oklass);
8441 } else if (klass == mono_defaults.object_class)
8444 return mono_class_has_parent (oklass, klass);
8447 /*Check if @oklass is variant compatible with @klass.*/
8449 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8452 MonoType **klass_argv, **oklass_argv;
8453 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8454 MonoGenericContainer *container = klass_gtd->generic_container;
8456 /*Viable candidates are instances of the same generic interface*/
8457 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8460 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8461 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8463 for (j = 0; j < container->type_argc; ++j) {
8464 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8465 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8467 if (param1_class->valuetype != param2_class->valuetype)
8471 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8472 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8474 if (param1_class != param2_class) {
8475 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8476 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8478 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8479 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8487 /*Check if @candidate implements the interface @target*/
8489 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8493 gboolean is_variant = mono_class_has_variant_generic_params (target);
8495 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8496 if (mono_class_is_variant_compatible_slow (target, candidate))
8501 if (candidate == target)
8504 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8505 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8506 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (candidate);
8508 if (tb && tb->interfaces) {
8509 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8510 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8511 MonoClass *iface_class;
8513 /* we can't realize the type here since it can do pretty much anything. */
8516 iface_class = mono_class_from_mono_type (iface->type);
8517 if (iface_class == target)
8519 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8521 if (mono_class_implement_interface_slow (target, iface_class))
8526 /*setup_interfaces don't mono_class_init anything*/
8527 /*FIXME this doesn't handle primitive type arrays.
8528 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8529 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8531 mono_class_setup_interfaces (candidate, &error);
8532 if (!mono_error_ok (&error)) {
8533 mono_error_cleanup (&error);
8537 for (i = 0; i < candidate->interface_count; ++i) {
8538 if (candidate->interfaces [i] == target)
8541 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8544 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8548 candidate = candidate->parent;
8549 } while (candidate);
8555 * Check if @oklass can be assigned to @klass.
8556 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8559 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8561 if (candidate == target)
8563 if (target == mono_defaults.object_class)
8566 if (mono_class_has_parent (candidate, target))
8569 /*If target is not an interface there is no need to check them.*/
8570 if (MONO_CLASS_IS_INTERFACE (target))
8571 return mono_class_implement_interface_slow (target, candidate);
8573 if (target->delegate && mono_class_has_variant_generic_params (target))
8574 return mono_class_is_variant_compatible (target, candidate, FALSE);
8577 MonoClass *eclass, *eoclass;
8579 if (target->rank != candidate->rank)
8582 /* vectors vs. one dimensional arrays */
8583 if (target->byval_arg.type != candidate->byval_arg.type)
8586 eclass = target->cast_class;
8587 eoclass = candidate->cast_class;
8590 * a is b does not imply a[] is b[] when a is a valuetype, and
8591 * b is a reference type.
8594 if (eoclass->valuetype) {
8595 if ((eclass == mono_defaults.enum_class) ||
8596 (eclass == mono_defaults.enum_class->parent) ||
8597 (eclass == mono_defaults.object_class))
8601 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8603 /*FIXME properly handle nullables */
8604 /*FIXME properly handle (M)VAR */
8609 * mono_class_get_cctor:
8610 * @klass: A MonoClass pointer
8612 * Returns: The static constructor of @klass if it exists, NULL otherwise.
8615 mono_class_get_cctor (MonoClass *klass)
8617 MonoCachedClassInfo cached_info;
8619 if (image_is_dynamic (klass->image)) {
8621 * has_cctor is not set for these classes because mono_class_init () is
8624 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8627 if (!klass->has_cctor)
8630 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8632 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8633 if (!mono_error_ok (&error))
8634 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8638 if (klass->generic_class && !klass->methods)
8639 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8641 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8645 * mono_class_get_finalizer:
8646 * @klass: The MonoClass pointer
8648 * Returns: The finalizer method of @klass if it exists, NULL otherwise.
8651 mono_class_get_finalizer (MonoClass *klass)
8653 MonoCachedClassInfo cached_info;
8656 mono_class_init (klass);
8657 if (!mono_class_has_finalizer (klass))
8660 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8662 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8663 if (!mono_error_ok (&error))
8664 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8667 mono_class_setup_vtable (klass);
8668 return klass->vtable [finalize_slot];
8673 * mono_class_needs_cctor_run:
8674 * @klass: the MonoClass pointer
8675 * @caller: a MonoMethod describing the caller
8677 * Determines whenever the class has a static constructor and whenever it
8678 * needs to be called when executing CALLER.
8681 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8685 method = mono_class_get_cctor (klass);
8687 return (method == caller) ? FALSE : TRUE;
8693 * mono_class_array_element_size:
8696 * Returns: The number of bytes an element of type @klass
8697 * uses when stored into an array.
8700 mono_class_array_element_size (MonoClass *klass)
8702 MonoType *type = &klass->byval_arg;
8705 switch (type->type) {
8708 case MONO_TYPE_BOOLEAN:
8712 case MONO_TYPE_CHAR:
8721 case MONO_TYPE_CLASS:
8722 case MONO_TYPE_STRING:
8723 case MONO_TYPE_OBJECT:
8724 case MONO_TYPE_SZARRAY:
8725 case MONO_TYPE_ARRAY:
8726 return sizeof (gpointer);
8731 case MONO_TYPE_VALUETYPE:
8732 if (type->data.klass->enumtype) {
8733 type = mono_class_enum_basetype (type->data.klass);
8734 klass = klass->element_class;
8737 return mono_class_instance_size (klass) - sizeof (MonoObject);
8738 case MONO_TYPE_GENERICINST:
8739 type = &type->data.generic_class->container_class->byval_arg;
8742 case MONO_TYPE_MVAR: {
8745 return mono_type_size (type, &align);
8747 case MONO_TYPE_VOID:
8751 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8757 * mono_array_element_size:
8758 * @ac: pointer to a #MonoArrayClass
8760 * Returns: The size of single array element.
8763 mono_array_element_size (MonoClass *ac)
8765 g_assert (ac->rank);
8766 return ac->sizes.element_size;
8770 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8771 MonoGenericContext *context)
8774 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8775 g_assert (mono_error_ok (&error));
8780 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8781 MonoGenericContext *context, MonoError *error)
8783 mono_error_init (error);
8785 if (image_is_dynamic (image)) {
8786 MonoClass *tmp_handle_class;
8787 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context);
8789 g_assert (tmp_handle_class);
8791 *handle_class = tmp_handle_class;
8793 if (tmp_handle_class == mono_defaults.typehandle_class)
8794 return &((MonoClass*)obj)->byval_arg;
8799 switch (token & 0xff000000) {
8800 case MONO_TOKEN_TYPE_DEF:
8801 case MONO_TOKEN_TYPE_REF:
8802 case MONO_TOKEN_TYPE_SPEC: {
8805 *handle_class = mono_defaults.typehandle_class;
8806 type = mono_type_get_checked (image, token, context, error);
8810 mono_class_init (mono_class_from_mono_type (type));
8811 /* We return a MonoType* as handle */
8814 case MONO_TOKEN_FIELD_DEF: {
8816 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8818 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8822 *handle_class = mono_defaults.fieldhandle_class;
8823 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8827 mono_class_init (klass);
8828 return mono_class_get_field (klass, token);
8830 case MONO_TOKEN_METHOD_DEF:
8831 case MONO_TOKEN_METHOD_SPEC: {
8833 meth = mono_get_method_checked (image, token, NULL, context, error);
8835 *handle_class = mono_defaults.methodhandle_class;
8841 case MONO_TOKEN_MEMBER_REF: {
8842 guint32 cols [MONO_MEMBERREF_SIZE];
8844 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8845 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8846 mono_metadata_decode_blob_size (sig, &sig);
8847 if (*sig == 0x6) { /* it's a field */
8849 MonoClassField *field;
8850 field = mono_field_from_token_checked (image, token, &klass, context, error);
8852 *handle_class = mono_defaults.fieldhandle_class;
8856 meth = mono_get_method_checked (image, token, NULL, context, error);
8858 *handle_class = mono_defaults.methodhandle_class;
8863 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8869 * This function might need to call runtime functions so it can't be part
8870 * of the metadata library.
8872 static MonoLookupDynamicToken lookup_dynamic = NULL;
8875 mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
8877 lookup_dynamic = func;
8881 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context)
8883 MonoClass *handle_class;
8885 return lookup_dynamic (image, token, TRUE, &handle_class, context);
8889 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
8891 return lookup_dynamic (image, token, valid_token, handle_class, context);
8894 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8897 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8899 get_cached_class_info = func;
8903 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8905 if (!get_cached_class_info)
8908 return get_cached_class_info (klass, res);
8912 mono_install_get_class_from_name (MonoGetClassFromName func)
8914 get_class_from_name = func;
8918 * mono_class_get_image:
8920 * Use this method to get the `MonoImage*` where this class came from.
8922 * Returns: The image where this class is defined.
8925 mono_class_get_image (MonoClass *klass)
8927 return klass->image;
8931 * mono_class_get_element_class:
8932 * @klass: the MonoClass to act on
8934 * Use this function to get the element class of an array.
8936 * Returns: The element class of an array.
8939 mono_class_get_element_class (MonoClass *klass)
8941 return klass->element_class;
8945 * mono_class_is_valuetype:
8946 * @klass: the MonoClass to act on
8948 * Use this method to determine if the provided `MonoClass*` represents a value type,
8949 * or a reference type.
8951 * Returns: TRUE if the MonoClass represents a ValueType, FALSE if it represents a reference type.
8954 mono_class_is_valuetype (MonoClass *klass)
8956 return klass->valuetype;
8960 * mono_class_is_enum:
8961 * @klass: the MonoClass to act on
8963 * Use this function to determine if the provided `MonoClass*` represents an enumeration.
8965 * Returns: TRUE if the MonoClass represents an enumeration.
8968 mono_class_is_enum (MonoClass *klass)
8970 return klass->enumtype;
8974 * mono_class_enum_basetype:
8975 * @klass: the MonoClass to act on
8977 * Use this function to get the underlying type for an enumeration value.
8979 * Returns: The underlying type representation for an enumeration.
8982 mono_class_enum_basetype (MonoClass *klass)
8984 if (klass->element_class == klass)
8985 /* SRE or broken types */
8988 return &klass->element_class->byval_arg;
8992 * mono_class_get_parent
8993 * @klass: the MonoClass to act on
8995 * Returns: The parent class for this class.
8998 mono_class_get_parent (MonoClass *klass)
9000 return klass->parent;
9004 * mono_class_get_nesting_type:
9005 * @klass: the MonoClass to act on
9007 * Use this function to obtain the class that the provided `MonoClass*` is nested on.
9009 * If the return is NULL, this indicates that this class is not nested.
9011 * Returns: The container type where this type is nested or NULL if this type is not a nested type.
9014 mono_class_get_nesting_type (MonoClass *klass)
9016 return klass->nested_in;
9020 * mono_class_get_rank:
9021 * @klass: the MonoClass to act on
9023 * Returns: The rank for the array (the number of dimensions).
9026 mono_class_get_rank (MonoClass *klass)
9032 * mono_class_get_flags:
9033 * @klass: the MonoClass to act on
9035 * The type flags from the TypeDef table from the metadata.
9036 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
9039 * Returns: The flags from the TypeDef table.
9042 mono_class_get_flags (MonoClass *klass)
9044 return klass->flags;
9048 * mono_class_get_name
9049 * @klass: the MonoClass to act on
9051 * Returns: The name of the class.
9054 mono_class_get_name (MonoClass *klass)
9060 * mono_class_get_namespace:
9061 * @klass: the MonoClass to act on
9063 * Returns: The namespace of the class.
9066 mono_class_get_namespace (MonoClass *klass)
9068 return klass->name_space;
9072 * mono_class_get_type:
9073 * @klass: the MonoClass to act on
9075 * This method returns the internal Type representation for the class.
9077 * Returns: The MonoType from the class.
9080 mono_class_get_type (MonoClass *klass)
9082 return &klass->byval_arg;
9086 * mono_class_get_type_token:
9087 * @klass: the MonoClass to act on
9089 * This method returns type token for the class.
9091 * Returns: The type token for the class.
9094 mono_class_get_type_token (MonoClass *klass)
9096 return klass->type_token;
9100 * mono_class_get_byref_type:
9101 * @klass: the MonoClass to act on
9106 mono_class_get_byref_type (MonoClass *klass)
9108 return &klass->this_arg;
9112 * mono_class_num_fields:
9113 * @klass: the MonoClass to act on
9115 * Returns: The number of static and instance fields in the class.
9118 mono_class_num_fields (MonoClass *klass)
9120 return klass->field.count;
9124 * mono_class_num_methods:
9125 * @klass: the MonoClass to act on
9127 * Returns: The number of methods in the class.
9130 mono_class_num_methods (MonoClass *klass)
9132 return klass->method.count;
9136 * mono_class_num_properties
9137 * @klass: the MonoClass to act on
9139 * Returns: The number of properties in the class.
9142 mono_class_num_properties (MonoClass *klass)
9144 mono_class_setup_properties (klass);
9146 return klass->ext->property.count;
9150 * mono_class_num_events:
9151 * @klass: the MonoClass to act on
9153 * Returns: The number of events in the class.
9156 mono_class_num_events (MonoClass *klass)
9158 mono_class_setup_events (klass);
9160 return klass->ext->event.count;
9164 * mono_class_get_fields:
9165 * @klass: the MonoClass to act on
9167 * This routine is an iterator routine for retrieving the fields in a class.
9169 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9170 * iterate over all of the elements. When no more values are
9171 * available, the return value is NULL.
9173 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
9176 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9178 MonoClassField* field;
9182 mono_class_setup_fields_locking (klass);
9183 if (mono_class_has_failure (klass))
9185 /* start from the first */
9186 if (klass->field.count) {
9187 *iter = &klass->fields [0];
9188 return &klass->fields [0];
9194 field = (MonoClassField *)*iter;
9196 if (field < &klass->fields [klass->field.count]) {
9204 * mono_class_get_methods
9205 * @klass: the MonoClass to act on
9207 * This routine is an iterator routine for retrieving the fields in a class.
9209 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9210 * iterate over all of the elements. When no more values are
9211 * available, the return value is NULL.
9213 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
9216 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9218 MonoMethod** method;
9222 mono_class_setup_methods (klass);
9225 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9226 * FIXME we should better report this error to the caller
9228 if (!klass->methods)
9230 /* start from the first */
9231 if (klass->method.count) {
9232 *iter = &klass->methods [0];
9233 return klass->methods [0];
9239 method = (MonoMethod **)*iter;
9241 if (method < &klass->methods [klass->method.count]) {
9249 * mono_class_get_virtual_methods:
9251 * Iterate over the virtual methods of KLASS.
9253 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9256 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9258 MonoMethod** method;
9261 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9263 mono_class_setup_methods (klass);
9265 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9266 * FIXME we should better report this error to the caller
9268 if (!klass->methods)
9270 /* start from the first */
9271 method = &klass->methods [0];
9273 method = (MonoMethod **)*iter;
9276 while (method < &klass->methods [klass->method.count]) {
9277 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9281 if (method < &klass->methods [klass->method.count]) {
9288 /* Search directly in metadata to avoid calling setup_methods () */
9289 MonoMethod *res = NULL;
9295 start_index = GPOINTER_TO_UINT (*iter);
9298 for (i = start_index; i < klass->method.count; ++i) {
9301 /* klass->method.first points into the methodptr table */
9302 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
9304 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9308 if (i < klass->method.count) {
9310 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9311 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9313 /* Add 1 here so the if (*iter) check fails */
9314 *iter = GUINT_TO_POINTER (i + 1);
9323 * mono_class_get_properties:
9324 * @klass: the MonoClass to act on
9326 * This routine is an iterator routine for retrieving the properties in a class.
9328 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9329 * iterate over all of the elements. When no more values are
9330 * available, the return value is NULL.
9332 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9335 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9337 MonoProperty* property;
9341 mono_class_setup_properties (klass);
9342 /* start from the first */
9343 if (klass->ext->property.count) {
9344 *iter = &klass->ext->properties [0];
9345 return (MonoProperty *)*iter;
9351 property = (MonoProperty *)*iter;
9353 if (property < &klass->ext->properties [klass->ext->property.count]) {
9355 return (MonoProperty *)*iter;
9361 * mono_class_get_events:
9362 * @klass: the MonoClass to act on
9364 * This routine is an iterator routine for retrieving the properties in a class.
9366 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9367 * iterate over all of the elements. When no more values are
9368 * available, the return value is NULL.
9370 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9373 mono_class_get_events (MonoClass* klass, gpointer *iter)
9379 mono_class_setup_events (klass);
9380 /* start from the first */
9381 if (klass->ext->event.count) {
9382 *iter = &klass->ext->events [0];
9383 return (MonoEvent *)*iter;
9389 event = (MonoEvent *)*iter;
9391 if (event < &klass->ext->events [klass->ext->event.count]) {
9393 return (MonoEvent *)*iter;
9399 * mono_class_get_interfaces
9400 * @klass: the MonoClass to act on
9402 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9404 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9405 * iterate over all of the elements. When no more values are
9406 * available, the return value is NULL.
9408 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9411 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9419 mono_class_init (klass);
9420 if (!klass->interfaces_inited) {
9421 mono_class_setup_interfaces (klass, &error);
9422 if (!mono_error_ok (&error)) {
9423 mono_error_cleanup (&error);
9427 /* start from the first */
9428 if (klass->interface_count) {
9429 *iter = &klass->interfaces [0];
9430 return klass->interfaces [0];
9436 iface = (MonoClass **)*iter;
9438 if (iface < &klass->interfaces [klass->interface_count]) {
9446 setup_nested_types (MonoClass *klass)
9449 GList *classes, *nested_classes, *l;
9452 if (klass->nested_classes_inited)
9455 if (!klass->type_token)
9456 klass->nested_classes_inited = TRUE;
9458 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9462 guint32 cols [MONO_NESTED_CLASS_SIZE];
9463 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9464 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9465 if (!mono_error_ok (&error)) {
9466 /*FIXME don't swallow the error message*/
9467 mono_error_cleanup (&error);
9469 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9473 classes = g_list_prepend (classes, nclass);
9475 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9478 mono_class_alloc_ext (klass);
9480 nested_classes = NULL;
9481 for (l = classes; l; l = l->next)
9482 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9483 g_list_free (classes);
9485 mono_image_lock (klass->image);
9487 mono_memory_barrier ();
9488 if (!klass->nested_classes_inited) {
9489 klass->ext->nested_classes = nested_classes;
9490 mono_memory_barrier ();
9491 klass->nested_classes_inited = TRUE;
9494 mono_image_unlock (klass->image);
9498 * mono_class_get_nested_types
9499 * @klass: the MonoClass to act on
9501 * This routine is an iterator routine for retrieving the nested types of a class.
9502 * This works only if @klass is non-generic, or a generic type definition.
9504 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9505 * iterate over all of the elements. When no more values are
9506 * available, the return value is NULL.
9508 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9511 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9517 if (!klass->nested_classes_inited)
9518 setup_nested_types (klass);
9521 /* start from the first */
9522 if (klass->ext && klass->ext->nested_classes) {
9523 *iter = klass->ext->nested_classes;
9524 return (MonoClass *)klass->ext->nested_classes->data;
9526 /* no nested types */
9530 item = (GList *)*iter;
9534 return (MonoClass *)item->data;
9541 * mono_class_is_delegate
9542 * @klass: the MonoClass to act on
9544 * Returns: TRUE if the MonoClass represents a System.Delegate.
9547 mono_class_is_delegate (MonoClass *klass)
9549 return klass->delegate;
9553 * mono_class_implements_interface
9554 * @klass: The MonoClass to act on
9555 * @interface: The interface to check if @klass implements.
9557 * Returns: TRUE if @klass implements @interface.
9560 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9562 return mono_class_is_assignable_from (iface, klass);
9566 * mono_field_get_name:
9567 * @field: the MonoClassField to act on
9569 * Returns: The name of the field.
9572 mono_field_get_name (MonoClassField *field)
9578 * mono_field_get_type:
9579 * @field: the MonoClassField to act on
9581 * Returns: MonoType of the field.
9584 mono_field_get_type (MonoClassField *field)
9587 MonoType *type = mono_field_get_type_checked (field, &error);
9588 if (!mono_error_ok (&error)) {
9589 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9590 mono_error_cleanup (&error);
9597 * mono_field_get_type_checked:
9598 * @field: the MonoClassField to act on
9599 * @error: used to return any erro found while retrieving @field type
9601 * Returns: MonoType of the field.
9604 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9606 mono_error_init (error);
9608 mono_field_resolve_type (field, error);
9613 * mono_field_get_parent:
9614 * @field: the MonoClassField to act on
9616 * Returns: MonoClass where the field was defined.
9619 mono_field_get_parent (MonoClassField *field)
9621 return field->parent;
9625 * mono_field_get_flags;
9626 * @field: the MonoClassField to act on
9628 * The metadata flags for a field are encoded using the
9629 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9631 * Returns: The flags for the field.
9634 mono_field_get_flags (MonoClassField *field)
9637 return mono_field_resolve_flags (field);
9638 return field->type->attrs;
9642 * mono_field_get_offset:
9643 * @field: the MonoClassField to act on
9645 * Returns: The field offset.
9648 mono_field_get_offset (MonoClassField *field)
9650 return field->offset;
9654 mono_field_get_rva (MonoClassField *field)
9658 MonoClass *klass = field->parent;
9659 MonoFieldDefaultValue *field_def_values;
9661 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9663 if (!klass->ext || !klass->ext->field_def_values) {
9664 mono_class_alloc_ext (klass);
9666 field_def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9668 mono_image_lock (klass->image);
9669 if (!klass->ext->field_def_values)
9670 klass->ext->field_def_values = field_def_values;
9671 mono_image_unlock (klass->image);
9674 field_index = mono_field_get_index (field);
9676 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9677 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9679 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9680 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9683 return klass->ext->field_def_values [field_index].data;
9687 * mono_field_get_data:
9688 * @field: the MonoClassField to act on
9690 * Returns: A pointer to the metadata constant value or to the field
9691 * data if it has an RVA flag.
9694 mono_field_get_data (MonoClassField *field)
9696 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9697 MonoTypeEnum def_type;
9699 return mono_class_get_field_default_value (field, &def_type);
9700 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9701 return mono_field_get_rva (field);
9708 * mono_property_get_name:
9709 * @prop: the MonoProperty to act on
9711 * Returns: The name of the property
9714 mono_property_get_name (MonoProperty *prop)
9720 * mono_property_get_set_method
9721 * @prop: the MonoProperty to act on.
9723 * Returns: The setter method of the property (A MonoMethod)
9726 mono_property_get_set_method (MonoProperty *prop)
9732 * mono_property_get_get_method
9733 * @prop: the MonoProperty to act on.
9735 * Returns: The setter method of the property (A MonoMethod)
9738 mono_property_get_get_method (MonoProperty *prop)
9744 * mono_property_get_parent:
9745 * @prop: the MonoProperty to act on.
9747 * Returns: The MonoClass where the property was defined.
9750 mono_property_get_parent (MonoProperty *prop)
9752 return prop->parent;
9756 * mono_property_get_flags:
9757 * @prop: the MonoProperty to act on.
9759 * The metadata flags for a property are encoded using the
9760 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9762 * Returns: The flags for the property.
9765 mono_property_get_flags (MonoProperty *prop)
9771 * mono_event_get_name:
9772 * @event: the MonoEvent to act on
9774 * Returns: The name of the event.
9777 mono_event_get_name (MonoEvent *event)
9783 * mono_event_get_add_method:
9784 * @event: The MonoEvent to act on.
9786 * Returns: The @add' method for the event (a MonoMethod).
9789 mono_event_get_add_method (MonoEvent *event)
9795 * mono_event_get_remove_method:
9796 * @event: The MonoEvent to act on.
9798 * Returns: The @remove method for the event (a MonoMethod).
9801 mono_event_get_remove_method (MonoEvent *event)
9803 return event->remove;
9807 * mono_event_get_raise_method:
9808 * @event: The MonoEvent to act on.
9810 * Returns: The @raise method for the event (a MonoMethod).
9813 mono_event_get_raise_method (MonoEvent *event)
9815 return event->raise;
9819 * mono_event_get_parent:
9820 * @event: the MonoEvent to act on.
9822 * Returns: The MonoClass where the event is defined.
9825 mono_event_get_parent (MonoEvent *event)
9827 return event->parent;
9831 * mono_event_get_flags
9832 * @event: the MonoEvent to act on.
9834 * The metadata flags for an event are encoded using the
9835 * EVENT_* constants. See the tabledefs.h file for details.
9837 * Returns: The flags for the event.
9840 mono_event_get_flags (MonoEvent *event)
9842 return event->attrs;
9846 * mono_class_get_method_from_name:
9847 * @klass: where to look for the method
9848 * @name: name of the method
9849 * @param_count: number of parameters. -1 for any number.
9851 * Obtains a MonoMethod with a given name and number of parameters.
9852 * It only works if there are no multiple signatures for any given method name.
9855 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9857 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9861 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9863 MonoMethod *res = NULL;
9866 /* Search directly in the metadata to avoid calling setup_methods () */
9867 for (i = 0; i < klass->method.count; ++i) {
9869 guint32 cols [MONO_METHOD_SIZE];
9871 MonoMethodSignature *sig;
9873 /* klass->method.first points into the methodptr table */
9874 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9876 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9877 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9879 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9882 if (param_count == -1) {
9886 sig = mono_method_signature_checked (method, &error);
9888 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9891 if (sig->param_count == param_count) {
9902 * mono_class_get_method_from_name_flags:
9903 * @klass: where to look for the method
9904 * @name_space: name of the method
9905 * @param_count: number of parameters. -1 for any number.
9906 * @flags: flags which must be set in the method
9908 * Obtains a MonoMethod with a given name and number of parameters.
9909 * It only works if there are no multiple signatures for any given method name.
9912 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9914 MonoMethod *res = NULL;
9917 mono_class_init (klass);
9919 if (klass->generic_class && !klass->methods) {
9920 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9923 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9924 if (!mono_error_ok (&error))
9925 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9930 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9931 mono_class_setup_methods (klass);
9933 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9934 See mono/tests/array_load_exception.il
9935 FIXME we should better report this error to the caller
9937 if (!klass->methods)
9939 for (i = 0; i < klass->method.count; ++i) {
9940 MonoMethod *method = klass->methods [i];
9942 if (method->name[0] == name [0] &&
9943 !strcmp (name, method->name) &&
9944 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9945 ((method->flags & flags) == flags)) {
9952 res = find_method_in_metadata (klass, name, param_count, flags);
9959 * mono_class_set_failure:
9960 * @klass: class in which the failure was detected
9961 * @ex_type: the kind of exception/error to be thrown (later)
9962 * @ex_data: exception data (specific to each type of exception/error)
9964 * Keep a detected failure informations in the class for later processing.
9965 * Note that only the first failure is kept.
9967 * LOCKING: Acquires the loader lock.
9970 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9972 if (mono_class_has_failure (klass))
9975 mono_loader_lock ();
9976 klass->exception_type = ex_type;
9978 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9979 mono_loader_unlock ();
9985 * mono_class_get_exception_data:
9987 * Return the exception_data property of KLASS.
9989 * LOCKING: Acquires the loader lock.
9992 mono_class_get_exception_data (MonoClass *klass)
9994 return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9998 * mono_classes_init:
10000 * Initialize the resources used by this module.
10003 mono_classes_init (void)
10005 mono_os_mutex_init (&classes_mutex);
10007 mono_counters_register ("Inflated methods size",
10008 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
10009 mono_counters_register ("Inflated classes",
10010 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
10011 mono_counters_register ("Inflated classes size",
10012 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
10013 mono_counters_register ("MonoClass size",
10014 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
10015 mono_counters_register ("MonoClassExt size",
10016 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
10020 * mono_classes_cleanup:
10022 * Free the resources used by this module.
10025 mono_classes_cleanup (void)
10027 if (global_interface_bitset)
10028 mono_bitset_free (global_interface_bitset);
10029 global_interface_bitset = NULL;
10030 mono_os_mutex_destroy (&classes_mutex);
10034 * mono_class_get_exception_for_failure:
10035 * @klass: class in which the failure was detected
10037 * Return a constructed MonoException than the caller can then throw
10038 * using mono_raise_exception - or NULL if no failure is present (or
10039 * doesn't result in an exception).
10042 mono_class_get_exception_for_failure (MonoClass *klass)
10044 gpointer exception_data = mono_class_get_exception_data (klass);
10046 switch (mono_class_get_failure(klass)) {
10047 case MONO_EXCEPTION_TYPE_LOAD: {
10050 char *str = mono_type_get_full_name (klass);
10051 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
10052 name = mono_string_new (mono_domain_get (), str);
10054 ex = mono_get_exception_type_load (name, astr);
10058 case MONO_EXCEPTION_MISSING_METHOD: {
10059 char *class_name = (char *)exception_data;
10060 char *assembly_name = class_name + strlen (class_name) + 1;
10062 return mono_get_exception_missing_method (class_name, assembly_name);
10064 case MONO_EXCEPTION_MISSING_FIELD: {
10065 char *class_name = (char *)exception_data;
10066 char *member_name = class_name + strlen (class_name) + 1;
10068 return mono_get_exception_missing_field (class_name, member_name);
10070 case MONO_EXCEPTION_FILE_NOT_FOUND: {
10071 char *msg_format = (char *)exception_data;
10072 char *assembly_name = msg_format + strlen (msg_format) + 1;
10073 char *msg = g_strdup_printf (msg_format, assembly_name);
10076 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
10082 case MONO_EXCEPTION_BAD_IMAGE: {
10083 return mono_get_exception_bad_image_format ((const char *)exception_data);
10085 case MONO_EXCEPTION_INVALID_PROGRAM: {
10086 return mono_exception_from_name_msg (mono_defaults.corlib, "System", "InvalidProgramException", "");
10089 MonoLoaderError *error;
10092 error = mono_loader_get_last_error ();
10093 if (error != NULL){
10094 ex = mono_loader_error_prepare_exception (error);
10098 /* TODO - handle other class related failures */
10105 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
10107 outer_klass = mono_class_get_generic_type_definition (outer_klass);
10108 inner_klass = mono_class_get_generic_type_definition (inner_klass);
10110 if (outer_klass == inner_klass)
10112 inner_klass = inner_klass->nested_in;
10113 } while (inner_klass);
10118 mono_class_get_generic_type_definition (MonoClass *klass)
10120 return klass->generic_class ? klass->generic_class->container_class : klass;
10124 * Check if @klass is a subtype of @parent ignoring generic instantiations.
10126 * Generic instantiations are ignored for all super types of @klass.
10128 * Visibility checks ignoring generic instantiations.
10131 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
10134 klass = mono_class_get_generic_type_definition (klass);
10135 parent = mono_class_get_generic_type_definition (parent);
10136 mono_class_setup_supertypes (klass);
10138 for (i = 0; i < klass->idepth; ++i) {
10139 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
10145 * Subtype can only access parent members with family protection if the site object
10146 * is subclass of Subtype. For example:
10147 * class A { protected int x; }
10149 * void valid_access () {
10153 * void invalid_access () {
10160 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
10162 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
10165 if (context_klass == NULL)
10167 /*if access_klass is not member_klass context_klass must be type compat*/
10168 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10174 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10177 if (accessing == accessed)
10179 if (!accessed || !accessing)
10182 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10183 * anywhere so untrusted friends are not safe to access platform's code internals */
10184 if (mono_security_core_clr_enabled ()) {
10185 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10189 mono_assembly_load_friends (accessed);
10190 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10191 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10192 /* Be conservative with checks */
10193 if (!friend_->name)
10195 if (strcmp (accessing->aname.name, friend_->name))
10197 if (friend_->public_key_token [0]) {
10198 if (!accessing->aname.public_key_token [0])
10200 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10209 * If klass is a generic type or if it is derived from a generic type, return the
10210 * MonoClass of the generic definition
10211 * Returns NULL if not found
10214 get_generic_definition_class (MonoClass *klass)
10217 if (klass->generic_class && klass->generic_class->container_class)
10218 return klass->generic_class->container_class;
10219 klass = klass->parent;
10225 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10228 for (i = 0; i < ginst->type_argc; ++i) {
10229 MonoType *type = ginst->type_argv[i];
10230 switch (type->type) {
10231 case MONO_TYPE_SZARRAY:
10232 if (!can_access_type (access_klass, type->data.klass))
10235 case MONO_TYPE_ARRAY:
10236 if (!can_access_type (access_klass, type->data.array->eklass))
10239 case MONO_TYPE_PTR:
10240 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10243 case MONO_TYPE_CLASS:
10244 case MONO_TYPE_VALUETYPE:
10245 case MONO_TYPE_GENERICINST:
10246 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10256 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10260 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10263 if (access_klass->element_class && !access_klass->enumtype)
10264 access_klass = access_klass->element_class;
10266 if (member_klass->element_class && !member_klass->enumtype)
10267 member_klass = member_klass->element_class;
10269 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10271 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10274 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
10277 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10280 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10283 /*Non nested type with nested visibility. We just fail it.*/
10284 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10287 switch (access_level) {
10288 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10289 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10291 case TYPE_ATTRIBUTE_PUBLIC:
10294 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10297 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10298 return is_nesting_type (member_klass, access_klass);
10300 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10301 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10303 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10304 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10306 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10307 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10308 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10310 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10311 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10312 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10317 /* FIXME: check visibility of type, too */
10319 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10321 MonoClass *member_generic_def;
10322 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10325 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
10326 access_klass->generic_container) &&
10327 (member_generic_def = get_generic_definition_class (member_klass))) {
10328 MonoClass *access_container;
10330 if (access_klass->generic_container)
10331 access_container = access_klass;
10333 access_container = access_klass->generic_class->container_class;
10335 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10339 /* Partition I 8.5.3.2 */
10340 /* the access level values are the same for fields and methods */
10341 switch (access_level) {
10342 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10343 /* same compilation unit */
10344 return access_klass->image == member_klass->image;
10345 case FIELD_ATTRIBUTE_PRIVATE:
10346 return access_klass == member_klass;
10347 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10348 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10349 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10352 case FIELD_ATTRIBUTE_ASSEMBLY:
10353 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10354 case FIELD_ATTRIBUTE_FAMILY:
10355 if (is_valid_family_access (access_klass, member_klass, context_klass))
10358 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10359 if (is_valid_family_access (access_klass, member_klass, context_klass))
10361 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10362 case FIELD_ATTRIBUTE_PUBLIC:
10369 * mono_method_can_access_field:
10370 * @method: Method that will attempt to access the field
10371 * @field: the field to access
10373 * Used to determine if a method is allowed to access the specified field.
10375 * Returns: TRUE if the given @method is allowed to access the @field while following
10376 * the accessibility rules of the CLI.
10379 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10381 /* FIXME: check all overlapping fields */
10382 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10384 MonoClass *nested = method->klass->nested_in;
10386 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10389 nested = nested->nested_in;
10396 * mono_method_can_access_method:
10397 * @method: Method that will attempt to access the other method
10398 * @called: the method that we want to probe for accessibility.
10400 * Used to determine if the @method is allowed to access the specified @called method.
10402 * Returns: TRUE if the given @method is allowed to invoke the @called while following
10403 * the accessibility rules of the CLI.
10406 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10408 int can = can_access_member (method->klass, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10410 MonoClass *nested = method->klass->nested_in;
10412 can = can_access_member (nested, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10415 nested = nested->nested_in;
10420 * with generics calls to explicit interface implementations can be expressed
10421 * directly: the method is private, but we must allow it. This may be opening
10422 * a hole or the generics code should handle this differently.
10423 * Maybe just ensure the interface type is public.
10425 if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
10431 * mono_method_can_access_method_full:
10432 * @method: The caller method
10433 * @called: The called method
10434 * @context_klass: The static type on stack of the owner @called object used
10436 * This function must be used with instance calls, as they have more strict family accessibility.
10437 * It can be used with static methods, but context_klass should be NULL.
10439 * Returns: TRUE if caller have proper visibility and acessibility to @called
10442 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10444 MonoClass *access_class = method->klass;
10445 MonoClass *member_class = called->klass;
10446 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10448 MonoClass *nested = access_class->nested_in;
10450 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10453 nested = nested->nested_in;
10460 can = can_access_type (access_class, member_class);
10462 MonoClass *nested = access_class->nested_in;
10464 can = can_access_type (nested, member_class);
10467 nested = nested->nested_in;
10474 if (called->is_inflated) {
10475 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10476 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10485 * mono_method_can_access_field_full:
10486 * @method: The caller method
10487 * @field: The accessed field
10488 * @context_klass: The static type on stack of the owner @field object used
10490 * This function must be used with instance fields, as they have more strict family accessibility.
10491 * It can be used with static fields, but context_klass should be NULL.
10493 * Returns: TRUE if caller have proper visibility and acessibility to @field
10496 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10498 MonoClass *access_class = method->klass;
10499 MonoClass *member_class = field->parent;
10500 /* FIXME: check all overlapping fields */
10501 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10503 MonoClass *nested = access_class->nested_in;
10505 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10508 nested = nested->nested_in;
10515 can = can_access_type (access_class, member_class);
10517 MonoClass *nested = access_class->nested_in;
10519 can = can_access_type (nested, member_class);
10522 nested = nested->nested_in;
10532 * mono_class_can_access_class:
10533 * @source_class: The source class
10534 * @target_class: The accessed class
10536 * This function returns is @target_class is visible to @source_class
10538 * Returns: TRUE if source have proper visibility and acessibility to target
10541 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10543 return can_access_type (source_class, target_class);
10547 * mono_type_is_valid_enum_basetype:
10548 * @type: The MonoType to check
10550 * Returns: TRUE if the type can be used as the basetype of an enum
10552 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10553 switch (type->type) {
10556 case MONO_TYPE_BOOLEAN:
10559 case MONO_TYPE_CHAR:
10573 * mono_class_is_valid_enum:
10574 * @klass: An enum class to be validated
10576 * This method verify the required properties an enum should have.
10578 * Returns: TRUE if the informed enum class is valid
10580 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10581 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10582 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10584 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10585 MonoClassField * field;
10586 gpointer iter = NULL;
10587 gboolean found_base_field = FALSE;
10589 g_assert (klass->enumtype);
10590 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10591 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10595 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10598 while ((field = mono_class_get_fields (klass, &iter))) {
10599 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10600 if (found_base_field)
10602 found_base_field = TRUE;
10603 if (!mono_type_is_valid_enum_basetype (field->type))
10608 if (!found_base_field)
10611 if (klass->method.count > 0)
10618 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10620 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10624 * mono_class_setup_interface_id:
10626 * Initializes MonoClass::interface_id if required.
10628 * LOCKING: Acquires the loader lock.
10631 mono_class_setup_interface_id (MonoClass *klass)
10633 mono_loader_lock ();
10634 if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10635 klass->interface_id = mono_get_unique_iid (klass);
10636 mono_loader_unlock ();
10640 * mono_class_alloc_ext:
10642 * Allocate klass->ext if not already done.
10645 mono_class_alloc_ext (MonoClass *klass)
10652 ext = (MonoClassExt *)mono_class_alloc0 (klass, sizeof (MonoClassExt));
10653 mono_image_lock (klass->image);
10654 mono_memory_barrier ();
10657 class_ext_size += sizeof (MonoClassExt);
10658 mono_image_unlock (klass->image);
10662 * mono_class_setup_interfaces:
10664 * Initialize klass->interfaces/interfaces_count.
10665 * LOCKING: Acquires the loader lock.
10666 * This function can fail the type.
10669 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10671 int i, interface_count;
10672 MonoClass **interfaces;
10674 mono_error_init (error);
10676 if (klass->interfaces_inited)
10679 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10680 MonoType *args [1];
10682 /* generic IList, ICollection, IEnumerable */
10683 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10684 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10686 args [0] = &klass->element_class->byval_arg;
10687 interfaces [0] = mono_class_bind_generic_parameters (
10688 mono_defaults.generic_ilist_class, 1, args, FALSE);
10689 if (interface_count > 1)
10690 interfaces [1] = mono_class_bind_generic_parameters (
10691 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10692 } else if (klass->generic_class) {
10693 MonoClass *gklass = klass->generic_class->container_class;
10695 mono_class_setup_interfaces (gklass, error);
10696 if (!mono_error_ok (error)) {
10697 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10701 interface_count = gklass->interface_count;
10702 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10703 for (i = 0; i < interface_count; i++) {
10704 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10705 if (!mono_error_ok (error)) {
10706 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10711 interface_count = 0;
10715 mono_image_lock (klass->image);
10717 if (!klass->interfaces_inited) {
10718 klass->interface_count = interface_count;
10719 klass->interfaces = interfaces;
10721 mono_memory_barrier ();
10723 klass->interfaces_inited = TRUE;
10726 mono_image_unlock (klass->image);
10730 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10732 MonoClass *klass = field->parent;
10733 MonoImage *image = klass->image;
10734 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10735 int field_idx = field - klass->fields;
10737 mono_error_init (error);
10740 MonoClassField *gfield = >d->fields [field_idx];
10741 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10742 if (!mono_error_ok (error)) {
10743 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10744 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10747 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10748 if (!mono_error_ok (error)) {
10749 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10750 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10754 guint32 cols [MONO_FIELD_SIZE];
10755 MonoGenericContainer *container = NULL;
10756 int idx = klass->field.first + field_idx;
10758 /*FIXME, in theory we do not lazy load SRE fields*/
10759 g_assert (!image_is_dynamic (image));
10761 if (klass->generic_container) {
10762 container = klass->generic_container;
10764 container = gtd->generic_container;
10765 g_assert (container);
10768 /* klass->field.first and idx points into the fieldptr table */
10769 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10771 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10772 mono_error_set_type_load_class (error, klass, "Could not verify field %s signature", field->name);;
10773 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
10777 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10779 mono_metadata_decode_value (sig, &sig);
10780 /* FIELD signature == 0x06 */
10781 g_assert (*sig == 0x06);
10783 field->type = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10784 if (!field->type) {
10785 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10786 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10792 mono_field_resolve_flags (MonoClassField *field)
10794 MonoClass *klass = field->parent;
10795 MonoImage *image = klass->image;
10796 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10797 int field_idx = field - klass->fields;
10801 MonoClassField *gfield = >d->fields [field_idx];
10802 return mono_field_get_flags (gfield);
10804 int idx = klass->field.first + field_idx;
10806 /*FIXME, in theory we do not lazy load SRE fields*/
10807 g_assert (!image_is_dynamic (image));
10809 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10814 * mono_class_setup_basic_field_info:
10815 * @class: The class to initialize
10817 * Initializes the klass->fields array of fields.
10818 * Aquires the loader lock.
10821 mono_class_setup_basic_field_info_locking (MonoClass *klass)
10823 mono_loader_lock ();
10824 mono_class_setup_basic_field_info (klass);
10825 mono_loader_unlock ();
10829 * mono_class_get_fields_lazy:
10830 * @klass: the MonoClass to act on
10832 * This routine is an iterator routine for retrieving the fields in a class.
10833 * Only minimal information about fields are loaded. Accessors must be used
10834 * for all MonoClassField returned.
10836 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10837 * iterate over all of the elements. When no more values are
10838 * available, the return value is NULL.
10840 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10843 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10845 MonoClassField* field;
10849 mono_class_setup_basic_field_info_locking (klass);
10850 if (!klass->fields)
10852 /* start from the first */
10853 if (klass->field.count) {
10854 *iter = &klass->fields [0];
10855 return (MonoClassField *)*iter;
10861 field = (MonoClassField *)*iter;
10863 if (field < &klass->fields [klass->field.count]) {
10865 return (MonoClassField *)*iter;
10871 mono_class_full_name (MonoClass *klass)
10873 return mono_type_full_name (&klass->byval_arg);
10876 /* Declare all shared lazy type lookup functions */
10877 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, System.Runtime.InteropServices, SafeHandle)