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/image-internals.h>
22 #include <mono/metadata/assembly.h>
23 #include <mono/metadata/assembly-internals.h>
24 #include <mono/metadata/metadata.h>
25 #include <mono/metadata/metadata-internals.h>
26 #include <mono/metadata/profiler-private.h>
27 #include <mono/metadata/tabledefs.h>
28 #include <mono/metadata/tokentype.h>
29 #include <mono/metadata/class-internals.h>
30 #include <mono/metadata/object.h>
31 #include <mono/metadata/appdomain.h>
32 #include <mono/metadata/mono-endian.h>
33 #include <mono/metadata/debug-helpers.h>
34 #include <mono/metadata/reflection.h>
35 #include <mono/metadata/exception.h>
36 #include <mono/metadata/security-manager.h>
37 #include <mono/metadata/security-core-clr.h>
38 #include <mono/metadata/attrdefs.h>
39 #include <mono/metadata/gc-internals.h>
40 #include <mono/metadata/verify-internals.h>
41 #include <mono/metadata/mono-debug.h>
42 #include <mono/utils/mono-counters.h>
43 #include <mono/utils/mono-string.h>
44 #include <mono/utils/mono-error-internals.h>
45 #include <mono/utils/mono-logger-internals.h>
46 #include <mono/utils/mono-memory-model.h>
47 #include <mono/utils/atomic.h>
48 #include <mono/utils/bsearch.h>
49 #include <mono/utils/checked-build.h>
53 gboolean mono_print_vtable = FALSE;
54 gboolean mono_align_small_structs = FALSE;
57 guint32 inflated_classes, inflated_classes_size, inflated_methods_size;
58 guint32 classes_size, class_ext_size;
60 /* Low level lock which protects data structures in this module */
61 static mono_mutex_t classes_mutex;
63 /* Function supplied by the runtime to find classes by name using information from the AOT file */
64 static MonoGetClassFromName get_class_from_name = NULL;
66 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error);
67 static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
68 static gboolean can_access_type (MonoClass *access_klass, MonoClass *member_klass);
69 static MonoMethod* find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags);
70 static int generic_array_methods (MonoClass *klass);
71 static void setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos);
73 static MonoMethod* mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter);
74 static char* mono_assembly_name_from_token (MonoImage *image, guint32 type_token);
75 static void mono_field_resolve_type (MonoClassField *field, MonoError *error);
76 static guint32 mono_field_resolve_flags (MonoClassField *field);
77 static void mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup);
78 static void mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gklass);
81 We use gclass recording to allow recursive system f types to be referenced by a parent.
83 Given the following type hierarchy:
85 class TextBox : TextBoxBase<TextBox> {}
86 class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
87 class TextInput<T> : Input<T> where T: TextInput<T> {}
90 The runtime tries to load TextBoxBase<>.
91 To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
92 To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
93 To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
95 At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded
96 at this point, iow, both are registered in the type map and both and a NULL parent. This means
97 that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
99 To fix that what we do is to record all generic instantes created while resolving the parent of
100 any generic type definition and, after resolved, correct the parent field if needed.
103 static int record_gclass_instantiation;
104 static GSList *gclass_recorded_list;
105 typedef gboolean (*gclass_record_func) (MonoClass*, void*);
110 mono_locks_os_acquire (&classes_mutex, ClassesLock);
114 classes_unlock (void)
116 mono_locks_os_release (&classes_mutex, ClassesLock);
120 * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
123 enable_gclass_recording (void)
125 ++record_gclass_instantiation;
129 * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
132 disable_gclass_recording (gclass_record_func func, void *user_data)
134 GSList **head = &gclass_recorded_list;
136 g_assert (record_gclass_instantiation > 0);
137 --record_gclass_instantiation;
140 GSList *node = *head;
141 if (func ((MonoClass*)node->data, user_data)) {
143 g_slist_free_1 (node);
149 /* We automatically discard all recorded gclasses when disabled. */
150 if (!record_gclass_instantiation && gclass_recorded_list) {
151 g_slist_free (gclass_recorded_list);
152 gclass_recorded_list = NULL;
157 * mono_class_from_typeref:
158 * @image: a MonoImage
159 * @type_token: a TypeRef token
161 * Creates the MonoClass* structure representing the type defined by
162 * the typeref token valid inside @image.
163 * Returns: The MonoClass* representing the typeref token, NULL ifcould
167 mono_class_from_typeref (MonoImage *image, guint32 type_token)
170 MonoClass *klass = mono_class_from_typeref_checked (image, type_token, &error);
171 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
176 * mono_class_from_typeref_checked:
177 * @image: a MonoImage
178 * @type_token: a TypeRef token
179 * @error: error return code, if any.
181 * Creates the MonoClass* structure representing the type defined by
182 * the typeref token valid inside @image.
184 * Returns: The MonoClass* representing the typeref token, NULL if it could
185 * not be loaded with the @error value filled with the information about the
189 mono_class_from_typeref_checked (MonoImage *image, guint32 type_token, MonoError *error)
191 guint32 cols [MONO_TYPEREF_SIZE];
192 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
194 const char *name, *nspace;
195 MonoClass *res = NULL;
198 mono_error_init (error);
200 if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, error))
203 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
205 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
206 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
208 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
209 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
210 case MONO_RESOLUTION_SCOPE_MODULE:
212 LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
213 This is not the observed behavior of existing implementations.
214 The defacto behavior is that it's just a typedef in disguise.
216 /* a typedef in disguise */
217 res = mono_class_from_name_checked (image, nspace, name, error);
220 case MONO_RESOLUTION_SCOPE_MODULEREF:
221 module = mono_image_load_module_checked (image, idx, error);
223 res = mono_class_from_name_checked (module, nspace, name, error);
226 case MONO_RESOLUTION_SCOPE_TYPEREF: {
227 MonoClass *enclosing;
230 if (idx == mono_metadata_token_index (type_token)) {
231 mono_error_set_bad_image (error, image, "Image with self-referencing typeref token %08x.", type_token);
235 enclosing = mono_class_from_typeref_checked (image, MONO_TOKEN_TYPE_REF | idx, error);
236 return_val_if_nok (error, NULL);
238 if (enclosing->nested_classes_inited && enclosing->ext) {
239 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
240 for (tmp = enclosing->ext->nested_classes; tmp; tmp = tmp->next) {
241 res = (MonoClass *)tmp->data;
242 if (strcmp (res->name, name) == 0)
246 /* Don't call mono_class_init as we might've been called by it recursively */
247 int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
249 guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
250 guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
251 const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
253 if (strcmp (nname, name) == 0)
254 return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, error);
256 i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
259 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name);
262 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
266 if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) {
267 mono_error_set_bad_image (error, image, "Image with invalid assemblyref token %08x.", idx);
271 if (!image->references || !image->references [idx - 1])
272 mono_assembly_load_reference (image, idx - 1);
273 g_assert (image->references [idx - 1]);
275 /* If the assembly did not load, register this as a type load exception */
276 if (image->references [idx - 1] == REFERENCE_MISSING){
277 MonoAssemblyName aname;
280 mono_assembly_get_assemblyref (image, idx - 1, &aname);
281 human_name = mono_stringify_assembly_name (&aname);
282 mono_error_set_assembly_load_simple (error, human_name, image->assembly ? image->assembly->ref_only : FALSE);
286 res = mono_class_from_name_checked (image->references [idx - 1]->image, nspace, name, error);
289 /* Generic case, should be avoided for when a better error is possible. */
290 if (!res && mono_error_ok (error)) {
291 char *name = mono_class_name_from_token (image, type_token);
292 char *assembly = mono_assembly_name_from_token (image, type_token);
293 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
300 mono_image_memdup (MonoImage *image, void *data, guint size)
302 void *res = mono_image_alloc (image, size);
303 memcpy (res, data, size);
307 /* Copy everything mono_metadata_free_array free. */
309 mono_dup_array_type (MonoImage *image, MonoArrayType *a)
312 a = (MonoArrayType *)mono_image_memdup (image, a, sizeof (MonoArrayType));
314 a->sizes = (int *)mono_image_memdup (image, a->sizes, a->numsizes * sizeof (int));
316 a->lobounds = (int *)mono_image_memdup (image, a->lobounds, a->numlobounds * sizeof (int));
318 a = (MonoArrayType *)g_memdup (a, sizeof (MonoArrayType));
320 a->sizes = (int *)g_memdup (a->sizes, a->numsizes * sizeof (int));
322 a->lobounds = (int *)g_memdup (a->lobounds, a->numlobounds * sizeof (int));
327 /* Copy everything mono_metadata_free_method_signature free. */
329 mono_metadata_signature_deep_dup (MonoImage *image, MonoMethodSignature *sig)
333 sig = mono_metadata_signature_dup_full (image, sig);
335 sig->ret = mono_metadata_type_dup (image, sig->ret);
336 for (i = 0; i < sig->param_count; ++i)
337 sig->params [i] = mono_metadata_type_dup (image, sig->params [i]);
343 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
345 MonoAssembly *ta = klass->image->assembly;
348 name = mono_stringify_assembly_name (&ta->aname);
349 g_string_append_printf (str, ", %s", name);
354 mono_type_name_check_byref (MonoType *type, GString *str)
357 g_string_append_c (str, '&');
361 * mono_identifier_escape_type_name_chars:
362 * @str: a destination string
363 * @identifier: an IDENTIFIER in internal form
367 * The displayed form of the identifier is appended to str.
369 * The displayed form of an identifier has the characters ,+&*[]\
370 * that have special meaning in type names escaped with a preceeding
371 * backslash (\) character.
374 mono_identifier_escape_type_name_chars (GString* str, const char* identifier)
380 // reserve space for common case: there will be no escaped characters.
381 g_string_set_size(str, n + strlen(identifier));
382 g_string_set_size(str, n);
384 for (const char* s = identifier; *s != 0 ; s++) {
393 g_string_append_c (str, '\\');
394 g_string_append_c (str, *s);
397 g_string_append_c (str, *s);
405 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
406 MonoTypeNameFormat format)
410 switch (type->type) {
411 case MONO_TYPE_ARRAY: {
412 int i, rank = type->data.array->rank;
413 MonoTypeNameFormat nested_format;
415 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
416 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
418 mono_type_get_name_recurse (
419 &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
420 g_string_append_c (str, '[');
422 g_string_append_c (str, '*');
423 for (i = 1; i < rank; i++)
424 g_string_append_c (str, ',');
425 g_string_append_c (str, ']');
427 mono_type_name_check_byref (type, str);
429 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
430 _mono_type_get_assembly_name (type->data.array->eklass, str);
433 case MONO_TYPE_SZARRAY: {
434 MonoTypeNameFormat nested_format;
436 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
437 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
439 mono_type_get_name_recurse (
440 &type->data.klass->byval_arg, str, FALSE, nested_format);
441 g_string_append (str, "[]");
443 mono_type_name_check_byref (type, str);
445 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
446 _mono_type_get_assembly_name (type->data.klass, str);
449 case MONO_TYPE_PTR: {
450 MonoTypeNameFormat nested_format;
452 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
453 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
455 mono_type_get_name_recurse (
456 type->data.type, str, FALSE, nested_format);
457 g_string_append_c (str, '*');
459 mono_type_name_check_byref (type, str);
461 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
462 _mono_type_get_assembly_name (mono_class_from_mono_type (type->data.type), str);
467 if (!mono_generic_param_info (type->data.generic_param))
468 g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num);
470 g_string_append (str, mono_generic_param_info (type->data.generic_param)->name);
472 mono_type_name_check_byref (type, str);
476 klass = mono_class_from_mono_type (type);
477 if (klass->nested_in) {
478 mono_type_get_name_recurse (
479 &klass->nested_in->byval_arg, str, TRUE, format);
480 if (format == MONO_TYPE_NAME_FORMAT_IL)
481 g_string_append_c (str, '.');
483 g_string_append_c (str, '+');
484 } else if (*klass->name_space) {
485 if (format == MONO_TYPE_NAME_FORMAT_IL)
486 g_string_append (str, klass->name_space);
488 mono_identifier_escape_type_name_chars (str, klass->name_space);
489 g_string_append_c (str, '.');
491 if (format == MONO_TYPE_NAME_FORMAT_IL) {
492 char *s = strchr (klass->name, '`');
493 int len = s ? s - klass->name : strlen (klass->name);
494 g_string_append_len (str, klass->name, len);
496 mono_identifier_escape_type_name_chars (str, klass->name);
500 if (klass->generic_class) {
501 MonoGenericClass *gclass = klass->generic_class;
502 MonoGenericInst *inst = gclass->context.class_inst;
503 MonoTypeNameFormat nested_format;
506 nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
507 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
509 if (format == MONO_TYPE_NAME_FORMAT_IL)
510 g_string_append_c (str, '<');
512 g_string_append_c (str, '[');
513 for (i = 0; i < inst->type_argc; i++) {
514 MonoType *t = inst->type_argv [i];
517 g_string_append_c (str, ',');
518 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
519 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
520 g_string_append_c (str, '[');
521 mono_type_get_name_recurse (inst->type_argv [i], str, FALSE, nested_format);
522 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
523 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
524 g_string_append_c (str, ']');
526 if (format == MONO_TYPE_NAME_FORMAT_IL)
527 g_string_append_c (str, '>');
529 g_string_append_c (str, ']');
530 } else if (klass->generic_container &&
531 (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
532 (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
535 if (format == MONO_TYPE_NAME_FORMAT_IL)
536 g_string_append_c (str, '<');
538 g_string_append_c (str, '[');
539 for (i = 0; i < klass->generic_container->type_argc; i++) {
541 g_string_append_c (str, ',');
542 g_string_append (str, mono_generic_container_get_param_info (klass->generic_container, i)->name);
544 if (format == MONO_TYPE_NAME_FORMAT_IL)
545 g_string_append_c (str, '>');
547 g_string_append_c (str, ']');
550 mono_type_name_check_byref (type, str);
552 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
553 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
554 _mono_type_get_assembly_name (klass, str);
560 * mono_type_get_name_full:
562 * @format: the format for the return string.
565 * Returns: The string representation in a number of formats:
567 * if format is MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
568 * returned in the formatrequired by System.Reflection, this is the
569 * inverse of mono_reflection_parse_type ().
571 * if format is MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
572 * be used by the IL assembler.
574 * if format is MONO_TYPE_NAME_FORMAT_FULL_NAME
576 * if format is MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
579 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
583 result = g_string_new ("");
585 mono_type_get_name_recurse (type, result, FALSE, format);
587 return g_string_free (result, FALSE);
591 * mono_type_get_full_name:
594 * Returns: The string representation for type as required by System.Reflection.
595 * The inverse of mono_reflection_parse_type ().
598 mono_type_get_full_name (MonoClass *klass)
600 return mono_type_get_name_full (mono_class_get_type (klass), MONO_TYPE_NAME_FORMAT_REFLECTION);
604 * mono_type_get_name:
607 * Returns: The string representation for type as it would be represented in IL code.
610 mono_type_get_name (MonoType *type)
612 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
616 * mono_type_get_underlying_type:
619 * Returns: The MonoType for the underlying integer type if @type
620 * is an enum and byref is false, otherwise the type itself.
623 mono_type_get_underlying_type (MonoType *type)
625 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype && !type->byref)
626 return mono_class_enum_basetype (type->data.klass);
627 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype && !type->byref)
628 return mono_class_enum_basetype (type->data.generic_class->container_class);
633 * mono_class_is_open_constructed_type:
636 * Returns: TRUE if type represents a generics open constructed type.
637 * IOW, not all type parameters required for the instantiation have
638 * been provided or it's a generic type definition.
640 * An open constructed type means it's a non realizable type. Not to
641 * be mixed up with an abstract type - we can't cast or dispatch to
642 * an open type, for example.
645 mono_class_is_open_constructed_type (MonoType *t)
651 case MONO_TYPE_SZARRAY:
652 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
653 case MONO_TYPE_ARRAY:
654 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
656 return mono_class_is_open_constructed_type (t->data.type);
657 case MONO_TYPE_GENERICINST:
658 return t->data.generic_class->context.class_inst->is_open;
659 case MONO_TYPE_CLASS:
660 case MONO_TYPE_VALUETYPE:
661 return t->data.klass->generic_container != NULL;
668 This is a simple function to catch the most common bad instances of generic types.
669 Specially those that might lead to further failures in the runtime.
672 is_valid_generic_argument (MonoType *type)
674 switch (type->type) {
676 //case MONO_TYPE_TYPEDBYREF:
684 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
686 mono_error_init (error);
688 switch (type->type) {
689 case MONO_TYPE_MVAR: {
691 int num = mono_type_get_generic_param_num (type);
692 MonoGenericInst *inst = context->method_inst;
695 if (num >= inst->type_argc) {
696 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
697 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
698 num, info ? info->name : "", inst->type_argc);
702 if (!is_valid_generic_argument (inst->type_argv [num])) {
703 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
704 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
705 num, info ? info->name : "", inst->type_argv [num]->type);
709 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
710 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
711 * ->byref and ->attrs from @type are propagated to the returned type.
713 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
714 nt->byref = type->byref;
715 nt->attrs = type->attrs;
718 case MONO_TYPE_VAR: {
720 int num = mono_type_get_generic_param_num (type);
721 MonoGenericInst *inst = context->class_inst;
724 if (num >= inst->type_argc) {
725 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
726 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
727 num, info ? info->name : "", inst->type_argc);
730 if (!is_valid_generic_argument (inst->type_argv [num])) {
731 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
732 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
733 num, info ? info->name : "", inst->type_argv [num]->type);
736 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
737 nt->byref = type->byref;
738 nt->attrs = type->attrs;
741 case MONO_TYPE_SZARRAY: {
742 MonoClass *eclass = type->data.klass;
743 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
744 if (!inflated || !mono_error_ok (error))
746 nt = mono_metadata_type_dup (image, type);
747 nt->data.klass = mono_class_from_mono_type (inflated);
748 mono_metadata_free_type (inflated);
751 case MONO_TYPE_ARRAY: {
752 MonoClass *eclass = type->data.array->eklass;
753 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
754 if (!inflated || !mono_error_ok (error))
756 nt = mono_metadata_type_dup (image, type);
757 nt->data.array->eklass = mono_class_from_mono_type (inflated);
758 mono_metadata_free_type (inflated);
761 case MONO_TYPE_GENERICINST: {
762 MonoGenericClass *gclass = type->data.generic_class;
763 MonoGenericInst *inst;
765 if (!gclass->context.class_inst->is_open)
768 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
769 return_val_if_nok (error, NULL);
771 if (inst != gclass->context.class_inst)
772 gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
774 if (gclass == type->data.generic_class)
777 nt = mono_metadata_type_dup (image, type);
778 nt->data.generic_class = gclass;
781 case MONO_TYPE_CLASS:
782 case MONO_TYPE_VALUETYPE: {
783 MonoClass *klass = type->data.klass;
784 MonoGenericContainer *container = klass->generic_container;
785 MonoGenericInst *inst;
786 MonoGenericClass *gclass = NULL;
792 /* We can't use context->class_inst directly, since it can have more elements */
793 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
794 return_val_if_nok (error, NULL);
796 if (inst == container->context.class_inst)
799 gclass = mono_metadata_lookup_generic_class (klass, inst, image_is_dynamic (klass->image));
801 nt = mono_metadata_type_dup (image, type);
802 nt->type = MONO_TYPE_GENERICINST;
803 nt->data.generic_class = gclass;
813 mono_generic_class_get_context (MonoGenericClass *gclass)
815 return &gclass->context;
819 mono_class_get_context (MonoClass *klass)
821 return klass->generic_class ? mono_generic_class_get_context (klass->generic_class) : NULL;
825 * mono_class_get_generic_container:
827 * Return the generic container of KLASS which should be a generic type definition.
829 MonoGenericContainer*
830 mono_class_get_generic_container (MonoClass *klass)
832 g_assert (klass->is_generic);
834 return klass->generic_container;
838 * mono_class_get_generic_class:
840 * Return the MonoGenericClass of KLASS, which should be a generic instance.
843 mono_class_get_generic_class (MonoClass *klass)
845 g_assert (klass->is_inflated);
847 return klass->generic_class;
851 * mono_class_inflate_generic_type_with_mempool:
852 * @mempool: a mempool
854 * @context: a generics context
855 * @error: error context
857 * The same as mono_class_inflate_generic_type, but allocates the MonoType
858 * from mempool if it is non-NULL. If it is NULL, the MonoType is
859 * allocated on the heap and is owned by the caller.
860 * The returned type can potentially be the same as TYPE, so it should not be
861 * modified by the caller, and it should be freed using mono_metadata_free_type ().
864 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
866 MonoType *inflated = NULL;
867 mono_error_init (error);
870 inflated = inflate_generic_type (image, type, context, error);
871 return_val_if_nok (error, NULL);
874 MonoType *shared = mono_metadata_get_shared_type (type);
879 return mono_metadata_type_dup (image, type);
883 mono_stats.inflated_type_count++;
888 * mono_class_inflate_generic_type:
890 * @context: a generics context
892 * If @type is a generic type and @context is not NULL, instantiate it using the
893 * generics context @context.
895 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
896 * on the heap and is owned by the caller. Returns NULL on error.
898 * @deprecated Please use mono_class_inflate_generic_type_checked instead
901 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
905 result = mono_class_inflate_generic_type_checked (type, context, &error);
906 mono_error_cleanup (&error);
911 * mono_class_inflate_generic_type:
913 * @context: a generics context
914 * @error: error context to use
916 * If @type is a generic type and @context is not NULL, instantiate it using the
917 * generics context @context.
919 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
920 * on the heap and is owned by the caller.
923 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
925 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
929 * mono_class_inflate_generic_type_no_copy:
931 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
935 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
937 MonoType *inflated = NULL;
939 mono_error_init (error);
941 inflated = inflate_generic_type (image, type, context, error);
942 return_val_if_nok (error, NULL);
948 mono_stats.inflated_type_count++;
953 * mono_class_inflate_generic_class:
955 * Inflate the class @gklass with @context. Set @error on failure.
958 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
963 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
964 return_val_if_nok (error, NULL);
966 res = mono_class_from_mono_type (inflated);
967 mono_metadata_free_type (inflated);
972 static MonoGenericContext
973 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
975 MonoGenericInst *class_inst = NULL;
976 MonoGenericInst *method_inst = NULL;
977 MonoGenericContext res = { NULL, NULL };
979 mono_error_init (error);
981 if (context->class_inst) {
982 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
983 if (!mono_error_ok (error))
987 if (context->method_inst) {
988 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
989 if (!mono_error_ok (error))
993 res.class_inst = class_inst;
994 res.method_inst = method_inst;
1000 * mono_class_inflate_generic_method:
1001 * @method: a generic method
1002 * @context: a generics context
1004 * Instantiate the generic method @method using the generics context @context.
1006 * Returns: The new instantiated method
1009 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
1011 return mono_class_inflate_generic_method_full (method, NULL, context);
1015 mono_class_inflate_generic_method_checked (MonoMethod *method, MonoGenericContext *context, MonoError *error)
1017 return mono_class_inflate_generic_method_full_checked (method, NULL, context, error);
1021 * mono_class_inflate_generic_method_full:
1023 * Instantiate method @method with the generic context @context.
1024 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
1025 * Use mono_method_signature () and mono_method_get_header () to get the correct values.
1028 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
1031 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
1032 if (!mono_error_ok (&error))
1033 /*FIXME do proper error handling - on this case, kill this function. */
1034 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
1040 * mono_class_inflate_generic_method_full_checked:
1041 * Same as mono_class_inflate_generic_method_full but return failure using @error.
1044 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
1047 MonoMethodInflated *iresult, *cached;
1048 MonoMethodSignature *sig;
1049 MonoGenericContext tmp_context;
1051 mono_error_init (error);
1053 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1054 while (method->is_inflated) {
1055 MonoGenericContext *method_context = mono_method_get_context (method);
1056 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1058 tmp_context = inflate_generic_context (method_context, context, error);
1059 return_val_if_nok (error, NULL);
1061 context = &tmp_context;
1063 if (mono_metadata_generic_context_equal (method_context, context))
1066 method = imethod->declaring;
1070 * A method only needs to be inflated if the context has argument for which it is
1073 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1074 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1077 if (!((method->is_generic && context->method_inst) ||
1078 (method->klass->generic_container && context->class_inst)))
1081 iresult = g_new0 (MonoMethodInflated, 1);
1082 iresult->context = *context;
1083 iresult->declaring = method;
1085 if (!context->method_inst && method->is_generic)
1086 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1088 if (!context->class_inst) {
1089 g_assert (!iresult->declaring->klass->generic_class);
1090 if (iresult->declaring->klass->generic_container)
1091 iresult->context.class_inst = iresult->declaring->klass->generic_container->context.class_inst;
1092 else if (iresult->declaring->klass->generic_class)
1093 iresult->context.class_inst = iresult->declaring->klass->generic_class->context.class_inst;
1095 /* This can happen with some callers like mono_object_get_virtual_method () */
1096 if (!iresult->declaring->klass->generic_container && !iresult->declaring->klass->generic_class)
1097 iresult->context.class_inst = NULL;
1099 MonoImageSet *set = mono_metadata_get_image_set_for_method (iresult);
1102 mono_image_set_lock (set);
1103 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1104 mono_image_set_unlock (set);
1108 return (MonoMethod*)cached;
1111 mono_stats.inflated_method_count++;
1113 inflated_methods_size += sizeof (MonoMethodInflated);
1115 sig = mono_method_signature (method);
1117 char *name = mono_type_get_full_name (method->klass);
1118 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1124 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1126 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1129 result = (MonoMethod *) iresult;
1130 result->is_inflated = TRUE;
1131 result->is_generic = FALSE;
1132 result->sre_method = FALSE;
1133 result->signature = NULL;
1135 if (method->wrapper_type) {
1136 MonoMethodWrapper *mw = (MonoMethodWrapper*)method;
1137 MonoMethodWrapper *resw = (MonoMethodWrapper*)result;
1138 int len = GPOINTER_TO_INT (((void**)mw->method_data) [0]);
1140 resw->method_data = (void **)g_malloc (sizeof (gpointer) * (len + 1));
1141 memcpy (resw->method_data, mw->method_data, sizeof (gpointer) * (len + 1));
1144 if (iresult->context.method_inst) {
1145 /* Set the generic_container of the result to the generic_container of method */
1146 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1148 if (generic_container && iresult->context.method_inst == generic_container->context.method_inst) {
1149 result->is_generic = 1;
1150 mono_method_set_generic_container (result, generic_container);
1154 if (!klass_hint || !klass_hint->generic_class ||
1155 klass_hint->generic_class->container_class != method->klass ||
1156 klass_hint->generic_class->context.class_inst != context->class_inst)
1159 if (method->klass->generic_container)
1160 result->klass = klass_hint;
1162 if (!result->klass) {
1163 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1164 if (!mono_error_ok (error))
1167 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1169 mono_metadata_free_type (inflated);
1173 * FIXME: This should hold, but it doesn't:
1175 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1176 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1177 * g_assert (result->is_generic);
1180 * Fixing this here causes other things to break, hence a very
1181 * ugly hack in mini-trampolines.c - see
1182 * is_generic_method_definition().
1186 mono_image_set_lock (set);
1187 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1189 g_hash_table_insert (set->gmethod_cache, iresult, iresult);
1190 iresult->owner = set;
1193 mono_image_set_unlock (set);
1195 return (MonoMethod*)cached;
1203 * mono_get_inflated_method:
1205 * Obsolete. We keep it around since it's mentioned in the public API.
1208 mono_get_inflated_method (MonoMethod *method)
1214 * mono_method_get_context_general:
1216 * @uninflated: handle uninflated methods?
1218 * Returns the generic context of a method or NULL if it doesn't have
1219 * one. For an inflated method that's the context stored in the
1220 * method. Otherwise it's in the method's generic container or in the
1221 * generic container of the method's class.
1224 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1226 if (method->is_inflated) {
1227 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1228 return &imethod->context;
1232 if (method->is_generic)
1233 return &(mono_method_get_generic_container (method)->context);
1234 if (method->klass->generic_container)
1235 return &method->klass->generic_container->context;
1240 * mono_method_get_context:
1243 * Returns the generic context for method if it's inflated, otherwise
1247 mono_method_get_context (MonoMethod *method)
1249 return mono_method_get_context_general (method, FALSE);
1253 * mono_method_get_generic_container:
1255 * Returns the generic container of METHOD, which should be a generic method definition.
1256 * Returns NULL if METHOD is not a generic method definition.
1257 * LOCKING: Acquires the loader lock.
1259 MonoGenericContainer*
1260 mono_method_get_generic_container (MonoMethod *method)
1262 MonoGenericContainer *container;
1264 if (!method->is_generic)
1267 container = (MonoGenericContainer *)mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1268 g_assert (container);
1274 * mono_method_set_generic_container:
1276 * Sets the generic container of METHOD to CONTAINER.
1277 * LOCKING: Acquires the image lock.
1280 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1282 g_assert (method->is_generic);
1284 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1288 * mono_class_find_enum_basetype:
1289 * @class: The enum class
1291 * Determine the basetype of an enum by iterating through its fields. We do this
1292 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1295 mono_class_find_enum_basetype (MonoClass *klass, MonoError *error)
1297 MonoGenericContainer *container = NULL;
1298 MonoImage *m = klass->image;
1299 const int top = klass->field.count;
1302 g_assert (klass->enumtype);
1304 mono_error_init (error);
1306 if (klass->generic_container)
1307 container = klass->generic_container;
1308 else if (klass->generic_class) {
1309 MonoClass *gklass = klass->generic_class->container_class;
1311 container = gklass->generic_container;
1312 g_assert (container);
1316 * Fetch all the field information.
1318 for (i = 0; i < top; i++){
1320 guint32 cols [MONO_FIELD_SIZE];
1321 int idx = klass->field.first + i;
1324 /* klass->field.first and idx points into the fieldptr table */
1325 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1327 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1330 if (!mono_verifier_verify_field_signature (klass->image, cols [MONO_FIELD_SIGNATURE], NULL)) {
1331 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x", cols [MONO_FIELD_SIGNATURE]);
1335 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1336 mono_metadata_decode_value (sig, &sig);
1337 /* FIELD signature == 0x06 */
1339 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig);
1343 ftype = mono_metadata_parse_type_checked (m, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
1347 if (klass->generic_class) {
1348 //FIXME do we leak here?
1349 ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (klass), error);
1350 if (!mono_error_ok (error))
1352 ftype->attrs = cols [MONO_FIELD_FLAGS];
1357 mono_error_set_type_load_class (error, klass, "Could not find base type");
1364 * Checks for MonoClass::exception_type without resolving all MonoType's into MonoClass'es
1367 mono_type_has_exceptions (MonoType *type)
1369 switch (type->type) {
1370 case MONO_TYPE_CLASS:
1371 case MONO_TYPE_VALUETYPE:
1372 case MONO_TYPE_SZARRAY:
1373 return mono_class_has_failure (type->data.klass);
1374 case MONO_TYPE_ARRAY:
1375 return mono_class_has_failure (type->data.array->eklass);
1376 case MONO_TYPE_GENERICINST:
1377 return mono_class_has_failure (mono_generic_class_get_class (type->data.generic_class));
1384 mono_error_set_for_class_failure (MonoError *oerror, MonoClass *klass)
1386 gpointer exception_data = mono_class_get_exception_data (klass);
1388 switch (mono_class_get_failure(klass)) {
1389 case MONO_EXCEPTION_TYPE_LOAD: {
1390 mono_error_set_type_load_class (oerror, klass, "Error Loading class");
1393 case MONO_EXCEPTION_MISSING_METHOD: {
1394 char *class_name = (char *)exception_data;
1395 char *member_name = class_name + strlen (class_name) + 1;
1397 mono_error_set_method_load (oerror, klass, member_name, "Error Loading Method");
1400 case MONO_EXCEPTION_MISSING_FIELD: {
1401 char *class_name = (char *)exception_data;
1402 char *member_name = class_name + strlen (class_name) + 1;
1404 mono_error_set_field_load (oerror, klass, member_name, "Error Loading Field");
1407 case MONO_EXCEPTION_FILE_NOT_FOUND: {
1408 char *msg_format = (char *)exception_data;
1409 char *assembly_name = msg_format + strlen (msg_format) + 1;
1410 char *msg = g_strdup_printf (msg_format, assembly_name);
1412 mono_error_set_assembly_load (oerror, assembly_name, msg);
1415 case MONO_EXCEPTION_BAD_IMAGE: {
1416 mono_error_set_bad_image (oerror, NULL, (const char *)exception_data);
1419 case MONO_EXCEPTION_INVALID_PROGRAM: {
1420 mono_error_set_invalid_program (oerror, (const char *)exception_data);
1424 g_assert_not_reached ();
1433 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1437 mono_class_alloc (MonoClass *klass, int size)
1439 if (klass->generic_class)
1440 return mono_image_set_alloc (klass->generic_class->owner, size);
1442 return mono_image_alloc (klass->image, size);
1446 mono_class_alloc0 (MonoClass *klass, int size)
1450 res = mono_class_alloc (klass, size);
1451 memset (res, 0, size);
1455 #define mono_class_new0(klass,struct_type, n_structs) \
1456 ((struct_type *) mono_class_alloc0 ((klass), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1459 * mono_class_setup_basic_field_info:
1460 * @class: The class to initialize
1462 * Initializes the klass->fields.
1463 * LOCKING: Assumes the loader lock is held.
1466 mono_class_setup_basic_field_info (MonoClass *klass)
1468 MonoClassField *field;
1476 gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
1477 image = klass->image;
1478 top = klass->field.count;
1480 if (klass->generic_class && image_is_dynamic (klass->generic_class->container_class->image) && !klass->generic_class->container_class->wastypebuilder) {
1482 * This happens when a generic instance of an unfinished generic typebuilder
1483 * is used as an element type for creating an array type. We can't initialize
1484 * the fields of this class using the fields of gklass, since gklass is not
1485 * finished yet, fields could be added to it later.
1491 mono_class_setup_basic_field_info (gtd);
1493 top = gtd->field.count;
1494 klass->field.first = gtd->field.first;
1495 klass->field.count = gtd->field.count;
1498 klass->fields = (MonoClassField *)mono_class_alloc0 (klass, sizeof (MonoClassField) * top);
1501 * Fetch all the field information.
1503 for (i = 0; i < top; i++){
1504 field = &klass->fields [i];
1505 field->parent = klass;
1508 field->name = mono_field_get_name (>d->fields [i]);
1510 int idx = klass->field.first + i;
1511 /* klass->field.first and idx points into the fieldptr table */
1512 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1513 /* The name is needed for fieldrefs */
1514 field->name = mono_metadata_string_heap (image, name_idx);
1520 * mono_class_setup_fields:
1521 * @class: The class to initialize
1523 * Initializes the klass->fields.
1524 * LOCKING: Assumes the loader lock is held.
1527 mono_class_setup_fields (MonoClass *klass)
1530 MonoImage *m = klass->image;
1532 guint32 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1533 int i, blittable = TRUE;
1534 guint32 real_size = 0;
1535 guint32 packing_size = 0;
1537 gboolean explicit_size;
1538 MonoClassField *field;
1539 MonoGenericContainer *container = NULL;
1540 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
1543 * FIXME: We have a race condition here. It's possible that this function returns
1544 * to its caller with `instance_size` set to `0` instead of the actual size. This
1545 * is not a problem when the function is called recursively on the same class,
1546 * because the size will be initialized by the outer invocation. What follows is a
1547 * description of how it can occur in other cases, too. There it is a problem,
1548 * because it can lead to the GC being asked to allocate an object of size `0`,
1549 * which SGen chokes on. The race condition is triggered infrequently by
1550 * `tests/sgen-suspend.cs`.
1552 * This function is called for a class whenever one of its subclasses is inited.
1553 * For example, it's called for every subclass of Object. What it does is this:
1555 * if (klass->setup_fields_called)
1558 * klass->instance_size = 0;
1560 * klass->setup_fields_called = 1;
1561 * ... critical point
1562 * klass->instance_size = actual_instance_size;
1564 * The last two steps are sometimes reversed, but that only changes the way in which
1565 * the race condition works.
1567 * Assume thread A goes through this function and makes it to the critical point.
1568 * Now thread B runs the function and, since `setup_fields_called` is set, returns
1569 * immediately, but `instance_size` is incorrect.
1571 * The other case looks like this:
1573 * if (klass->setup_fields_called)
1575 * ... critical point X
1576 * klass->instance_size = 0;
1577 * ... critical point Y
1578 * klass->instance_size = actual_instance_size;
1580 * klass->setup_fields_called = 1;
1582 * Assume thread A goes through the function and makes it to critical point X. Now
1583 * thread B runs through the whole of the function, returning, assuming
1584 * `instance_size` is set. At that point thread A gets to run and makes it to
1585 * critical point Y, at which time `instance_size` is `0` again, invalidating thread
1588 if (klass->setup_fields_called)
1591 if (klass->generic_class && image_is_dynamic (klass->generic_class->container_class->image) && !klass->generic_class->container_class->wastypebuilder) {
1593 * This happens when a generic instance of an unfinished generic typebuilder
1594 * is used as an element type for creating an array type. We can't initialize
1595 * the fields of this class using the fields of gklass, since gklass is not
1596 * finished yet, fields could be added to it later.
1601 mono_class_setup_basic_field_info (klass);
1602 top = klass->field.count;
1605 mono_class_setup_fields (gtd);
1606 if (mono_class_has_failure (gtd)) {
1607 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1614 klass->sizes.class_size = 0;
1616 if (klass->parent) {
1617 /* For generic instances, klass->parent might not have been initialized */
1618 mono_class_init (klass->parent);
1619 if (!klass->parent->size_inited) {
1620 mono_class_setup_fields (klass->parent);
1621 if (mono_class_has_failure (klass->parent)) {
1622 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1626 instance_size += klass->parent->instance_size;
1627 klass->min_align = klass->parent->min_align;
1628 /* we use |= since it may have been set already */
1629 klass->has_references |= klass->parent->has_references;
1630 blittable = klass->parent->blittable;
1632 instance_size = sizeof (MonoObject);
1633 klass->min_align = 1;
1636 /* We can't really enable 16 bytes alignment until the GC supports it.
1637 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1638 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1639 Bug #506144 is an example of this issue.
1641 if (klass->simd_type)
1642 klass->min_align = 16;
1644 /* Get the real size */
1645 explicit_size = mono_metadata_packing_from_typedef (klass->image, klass->type_token, &packing_size, &real_size);
1647 if (explicit_size) {
1648 if ((packing_size & 0xffffff00) != 0) {
1649 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, packing_size);
1650 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
1653 klass->packing_size = packing_size;
1654 real_size += instance_size;
1658 if (explicit_size && real_size) {
1659 instance_size = MAX (real_size, instance_size);
1661 klass->blittable = blittable;
1662 if (!klass->instance_size)
1663 klass->instance_size = instance_size;
1664 mono_memory_barrier ();
1665 klass->size_inited = 1;
1666 klass->fields_inited = 1;
1667 klass->setup_fields_called = 1;
1671 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(mono_is_corlib_image (klass->image) && !strcmp (klass->name_space, "System") && !strcmp (klass->name, "ValueType")))
1674 /* Prevent infinite loops if the class references itself */
1675 klass->setup_fields_called = 1;
1677 if (klass->generic_container) {
1678 container = klass->generic_container;
1680 container = gtd->generic_container;
1681 g_assert (container);
1685 * Fetch all the field information.
1687 for (i = 0; i < top; i++){
1688 int idx = klass->field.first + i;
1689 field = &klass->fields [i];
1691 field->parent = klass;
1694 mono_field_resolve_type (field, &error);
1695 if (!mono_error_ok (&error)) {
1696 /*mono_field_resolve_type already failed class*/
1697 mono_error_cleanup (&error);
1701 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(klass), field->name);
1702 g_assert (field->type);
1705 if (mono_field_is_deleted (field))
1708 MonoClassField *gfield = >d->fields [i];
1709 field->offset = gfield->offset;
1711 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1713 mono_metadata_field_info (m, idx, &offset, NULL, NULL);
1714 field->offset = offset;
1716 if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1717 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Missing field layout info for %s", field->name));
1720 if (field->offset < -1) { /*-1 is used to encode special static fields */
1721 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Invalid negative field offset %d for %s", field->offset, field->name));
1724 if (klass->generic_container) {
1725 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic class cannot have explicit layout."));
1731 /* Only do these checks if we still think this type is blittable */
1732 if (blittable && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1733 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1736 MonoClass *field_class = mono_class_from_mono_type (field->type);
1738 mono_class_setup_fields (field_class);
1739 if (mono_class_has_failure (field_class)) {
1740 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1744 if (!field_class || !field_class->blittable)
1749 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1750 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
1751 blittable = klass->element_class->blittable;
1754 if (mono_type_has_exceptions (field->type)) {
1755 char *class_name = mono_type_get_full_name (klass);
1756 char *type_name = mono_type_full_name (field->type);
1758 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1759 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1760 g_free (class_name);
1764 /* The def_value of fields is compute lazily during vtable creation */
1767 if (klass == mono_defaults.string_class)
1770 klass->blittable = blittable;
1772 if (klass->enumtype && !mono_class_enum_basetype (klass)) {
1773 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1776 if (explicit_size && real_size) {
1777 instance_size = MAX (real_size, instance_size);
1780 if (mono_class_has_failure (klass))
1782 mono_class_layout_fields (klass, instance_size);
1784 /*valuetypes can't be neither bigger than 1Mb or empty. */
1785 if (klass->valuetype && (klass->instance_size <= 0 || klass->instance_size > (0x100000 + sizeof (MonoObject))))
1786 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1788 mono_memory_barrier ();
1789 klass->fields_inited = 1;
1793 * mono_class_setup_fields_locking:
1794 * @class: The class to initialize
1796 * Initializes the klass->fields array of fields.
1797 * Aquires the loader lock.
1800 mono_class_setup_fields_locking (MonoClass *klass)
1802 /* This can be checked without locks */
1803 if (klass->fields_inited)
1805 mono_loader_lock ();
1806 mono_class_setup_fields (klass);
1807 mono_loader_unlock ();
1811 * mono_class_has_references:
1813 * Returns whenever @klass->has_references is set, initializing it if needed.
1814 * Aquires the loader lock.
1817 mono_class_has_references (MonoClass *klass)
1819 if (klass->init_pending) {
1820 /* Be conservative */
1823 mono_class_init (klass);
1825 return klass->has_references;
1830 * mono_type_get_basic_type_from_generic:
1833 * Returns a closed type corresponding to the possibly open type
1837 mono_type_get_basic_type_from_generic (MonoType *type)
1839 /* When we do generic sharing we let type variables stand for reference/primitive types. */
1840 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) &&
1841 (!type->data.generic_param->gshared_constraint || type->data.generic_param->gshared_constraint->type == MONO_TYPE_OBJECT))
1842 return &mono_defaults.object_class->byval_arg;
1847 type_has_references (MonoClass *klass, MonoType *ftype)
1849 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)))))
1851 if (!ftype->byref && (ftype->type == MONO_TYPE_VAR || ftype->type == MONO_TYPE_MVAR)) {
1852 MonoGenericParam *gparam = ftype->data.generic_param;
1854 if (gparam->gshared_constraint)
1855 return mono_class_has_references (mono_class_from_mono_type (gparam->gshared_constraint));
1861 * mono_class_layout_fields:
1863 * @instance_size: base instance size
1865 * Compute the placement of fields inside an object or struct, according to
1866 * the layout rules and set the following fields in @class:
1867 * - has_references (if the class contains instance references firled or structs that contain references)
1868 * - has_static_refs (same, but for static fields)
1869 * - instance_size (size of the object in memory)
1870 * - class_size (size needed for the static fields)
1871 * - size_inited (flag set when the instance_size is set)
1873 * LOCKING: this is supposed to be called with the loader lock held.
1876 mono_class_layout_fields (MonoClass *klass, int instance_size)
1879 const int top = klass->field.count;
1880 guint32 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1881 guint32 pass, passes, real_size;
1882 gboolean gc_aware_layout = FALSE;
1883 gboolean has_static_fields = FALSE;
1884 MonoClassField *field;
1887 * When we do generic sharing we need to have layout
1888 * information for open generic classes (either with a generic
1889 * context containing type variables or with a generic
1890 * container), so we don't return in that case anymore.
1894 * Enable GC aware auto layout: in this mode, reference
1895 * fields are grouped together inside objects, increasing collector
1897 * Requires that all classes whose layout is known to native code be annotated
1898 * with [StructLayout (LayoutKind.Sequential)]
1899 * Value types have gc_aware_layout disabled by default, as per
1900 * what the default is for other runtimes.
1902 /* corlib is missing [StructLayout] directives in many places */
1903 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1904 if (!klass->valuetype)
1905 gc_aware_layout = TRUE;
1908 /* Compute klass->has_references */
1910 * Process non-static fields first, since static fields might recursively
1911 * refer to the class itself.
1913 for (i = 0; i < top; i++) {
1916 field = &klass->fields [i];
1918 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1919 ftype = mono_type_get_underlying_type (field->type);
1920 ftype = mono_type_get_basic_type_from_generic (ftype);
1921 if (type_has_references (klass, ftype))
1922 klass->has_references = TRUE;
1926 for (i = 0; i < top; i++) {
1929 field = &klass->fields [i];
1931 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1932 ftype = mono_type_get_underlying_type (field->type);
1933 ftype = mono_type_get_basic_type_from_generic (ftype);
1934 if (type_has_references (klass, ftype))
1935 klass->has_static_refs = TRUE;
1939 for (i = 0; i < top; i++) {
1942 field = &klass->fields [i];
1944 ftype = mono_type_get_underlying_type (field->type);
1945 ftype = mono_type_get_basic_type_from_generic (ftype);
1946 if (type_has_references (klass, ftype)) {
1947 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1948 klass->has_static_refs = TRUE;
1950 klass->has_references = TRUE;
1955 * Compute field layout and total size (not considering static fields)
1958 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1959 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1961 if (gc_aware_layout)
1966 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1969 if (klass->parent) {
1970 mono_class_setup_fields (klass->parent);
1971 if (mono_class_has_failure (klass->parent)) {
1972 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1975 real_size = klass->parent->instance_size;
1977 real_size = sizeof (MonoObject);
1980 for (pass = 0; pass < passes; ++pass) {
1981 for (i = 0; i < top; i++){
1986 field = &klass->fields [i];
1988 if (mono_field_is_deleted (field))
1990 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1993 ftype = mono_type_get_underlying_type (field->type);
1994 ftype = mono_type_get_basic_type_from_generic (ftype);
1995 if (gc_aware_layout) {
1996 if (type_has_references (klass, ftype)) {
2005 if ((top == 1) && (klass->instance_size == sizeof (MonoObject)) &&
2006 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
2007 /* This field is a hack inserted by MCS to empty structures */
2011 size = mono_type_size (field->type, &align);
2013 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
2014 align = klass->packing_size ? MIN (klass->packing_size, align): align;
2015 /* if the field has managed references, we need to force-align it
2018 if (type_has_references (klass, ftype))
2019 align = MAX (align, sizeof (gpointer));
2021 klass->min_align = MAX (align, klass->min_align);
2022 field->offset = real_size;
2024 field->offset += align - 1;
2025 field->offset &= ~(align - 1);
2027 /*TypeBuilders produce all sort of weird things*/
2028 g_assert (image_is_dynamic (klass->image) || field->offset > 0);
2029 real_size = field->offset + size;
2032 instance_size = MAX (real_size, instance_size);
2034 if (instance_size & (klass->min_align - 1)) {
2035 instance_size += klass->min_align - 1;
2036 instance_size &= ~(klass->min_align - 1);
2040 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
2044 for (i = 0; i < top; i++) {
2049 field = &klass->fields [i];
2052 * There must be info about all the fields in a type if it
2053 * uses explicit layout.
2055 if (mono_field_is_deleted (field))
2057 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2060 size = mono_type_size (field->type, &align);
2061 align = klass->packing_size ? MIN (klass->packing_size, align): align;
2062 klass->min_align = MAX (align, klass->min_align);
2065 * When we get here, field->offset is already set by the
2066 * loader (for either runtime fields or fields loaded from metadata).
2067 * The offset is from the start of the object: this works for both
2068 * classes and valuetypes.
2070 field->offset += sizeof (MonoObject);
2071 ftype = mono_type_get_underlying_type (field->type);
2072 ftype = mono_type_get_basic_type_from_generic (ftype);
2073 if (type_has_references (klass, ftype)) {
2074 if (field->offset % sizeof (gpointer)) {
2075 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
2082 real_size = MAX (real_size, size + field->offset);
2085 if (klass->has_references) {
2086 ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
2088 /* Check for overlapping reference and non-reference fields */
2089 for (i = 0; i < top; i++) {
2092 field = &klass->fields [i];
2094 if (mono_field_is_deleted (field))
2096 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2098 ftype = mono_type_get_underlying_type (field->type);
2099 if (MONO_TYPE_IS_REFERENCE (ftype))
2100 ref_bitmap [field->offset / sizeof (gpointer)] = 1;
2102 for (i = 0; i < top; i++) {
2103 field = &klass->fields [i];
2105 if (mono_field_is_deleted (field))
2107 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2110 // FIXME: Too much code does this
2112 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field->offset / sizeof (gpointer)]) {
2113 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);
2114 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
2118 g_free (ref_bitmap);
2121 instance_size = MAX (real_size, instance_size);
2122 if (instance_size & (klass->min_align - 1)) {
2123 instance_size += klass->min_align - 1;
2124 instance_size &= ~(klass->min_align - 1);
2130 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2132 * This leads to all kinds of problems with nested structs, so only
2133 * enable it when a MONO_DEBUG property is set.
2135 * For small structs, set min_align to at least the struct size to improve
2136 * performance, and since the JIT memset/memcpy code assumes this and generates
2137 * unaligned accesses otherwise. See #78990 for a testcase.
2139 if (mono_align_small_structs) {
2140 if (instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2141 klass->min_align = MAX (klass->min_align, instance_size - sizeof (MonoObject));
2145 if (klass->instance_size && !klass->image->dynamic) {
2146 /* Might be already set using cached info */
2147 g_assert (klass->instance_size == instance_size);
2149 klass->instance_size = instance_size;
2151 mono_memory_barrier ();
2152 klass->size_inited = 1;
2155 * Compute static field layout and size
2157 for (i = 0; i < top; i++){
2161 field = &klass->fields [i];
2163 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2165 if (mono_field_is_deleted (field))
2168 if (mono_type_has_exceptions (field->type)) {
2169 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
2173 has_static_fields = TRUE;
2175 size = mono_type_size (field->type, &align);
2176 field->offset = klass->sizes.class_size;
2177 /*align is always non-zero here*/
2178 field->offset += align - 1;
2179 field->offset &= ~(align - 1);
2180 klass->sizes.class_size = field->offset + size;
2183 if (has_static_fields && klass->sizes.class_size == 0)
2184 /* Simplify code which depends on class_size != 0 if the class has static fields */
2185 klass->sizes.class_size = 8;
2189 create_array_method (MonoClass *klass, const char *name, MonoMethodSignature *sig)
2193 method = (MonoMethod *) mono_image_alloc0 (klass->image, sizeof (MonoMethodPInvoke));
2194 method->klass = klass;
2195 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2196 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2197 method->signature = sig;
2198 method->name = name;
2201 if (name [0] == '.') {
2202 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2204 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2210 * mono_class_setup_methods:
2213 * Initializes the 'methods' array in CLASS.
2214 * Calling this method should be avoided if possible since it allocates a lot
2215 * of long-living MonoMethod structures.
2216 * Methods belonging to an interface are assigned a sequential slot starting
2219 * On failure this function sets klass->exception_type
2222 mono_class_setup_methods (MonoClass *klass)
2225 MonoMethod **methods;
2230 if (klass->generic_class) {
2232 MonoClass *gklass = klass->generic_class->container_class;
2234 mono_class_init (gklass);
2235 if (!mono_class_has_failure (gklass))
2236 mono_class_setup_methods (gklass);
2237 if (mono_class_has_failure (gklass)) {
2238 /* FIXME make exception_data less opaque so it's possible to dup it here */
2239 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2243 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2244 count = gklass->method.count;
2245 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * (count + 1));
2247 for (i = 0; i < count; i++) {
2248 methods [i] = mono_class_inflate_generic_method_full_checked (
2249 gklass->methods [i], klass, mono_class_get_context (klass), &error);
2250 if (!mono_error_ok (&error)) {
2251 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2252 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)));
2255 mono_error_cleanup (&error);
2259 } else if (klass->rank) {
2261 MonoMethod *amethod;
2262 MonoMethodSignature *sig;
2263 int count_generic = 0, first_generic = 0;
2265 gboolean jagged_ctor = FALSE;
2267 count = 3 + (klass->rank > 1? 2: 1);
2269 mono_class_setup_interfaces (klass, &error);
2270 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2272 if (klass->rank == 1 && klass->element_class->rank) {
2274 klass->method.count ++;
2277 if (klass->interface_count) {
2278 count_generic = generic_array_methods (klass);
2279 first_generic = count;
2280 count += klass->interface_count * count_generic;
2283 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * count);
2285 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
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;
2292 amethod = create_array_method (klass, ".ctor", sig);
2293 methods [method_num++] = amethod;
2294 if (klass->rank > 1) {
2295 sig = mono_metadata_signature_alloc (klass->image, klass->rank * 2);
2296 sig->ret = &mono_defaults.void_class->byval_arg;
2297 sig->pinvoke = TRUE;
2298 sig->hasthis = TRUE;
2299 for (i = 0; i < klass->rank * 2; ++i)
2300 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2302 amethod = create_array_method (klass, ".ctor", sig);
2303 methods [method_num++] = amethod;
2307 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2308 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2309 sig->ret = &mono_defaults.void_class->byval_arg;
2310 sig->pinvoke = TRUE;
2311 sig->hasthis = TRUE;
2312 for (i = 0; i < klass->rank + 1; ++i)
2313 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2314 amethod = create_array_method (klass, ".ctor", sig);
2315 methods [method_num++] = amethod;
2318 /* element Get (idx11, [idx2, ...]) */
2319 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2320 sig->ret = &klass->element_class->byval_arg;
2321 sig->pinvoke = TRUE;
2322 sig->hasthis = TRUE;
2323 for (i = 0; i < klass->rank; ++i)
2324 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2325 amethod = create_array_method (klass, "Get", sig);
2326 methods [method_num++] = amethod;
2327 /* element& Address (idx11, [idx2, ...]) */
2328 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2329 sig->ret = &klass->element_class->this_arg;
2330 sig->pinvoke = TRUE;
2331 sig->hasthis = TRUE;
2332 for (i = 0; i < klass->rank; ++i)
2333 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2334 amethod = create_array_method (klass, "Address", sig);
2335 methods [method_num++] = amethod;
2336 /* void Set (idx11, [idx2, ...], element) */
2337 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2338 sig->ret = &mono_defaults.void_class->byval_arg;
2339 sig->pinvoke = TRUE;
2340 sig->hasthis = TRUE;
2341 for (i = 0; i < klass->rank; ++i)
2342 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2343 sig->params [i] = &klass->element_class->byval_arg;
2344 amethod = create_array_method (klass, "Set", sig);
2345 methods [method_num++] = amethod;
2347 for (i = 0; i < klass->interface_count; i++)
2348 setup_generic_array_ifaces (klass, klass->interfaces [i], methods, first_generic + i * count_generic);
2352 count = klass->method.count;
2353 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * count);
2354 for (i = 0; i < count; ++i) {
2355 int idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_METHOD, klass->method.first + i + 1);
2356 methods [i] = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | idx, klass, NULL, &error);
2358 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)));
2359 mono_error_cleanup (&error);
2364 if (MONO_CLASS_IS_INTERFACE (klass)) {
2366 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2367 for (i = 0; i < count; ++i) {
2368 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2369 methods [i]->slot = slot++;
2373 mono_image_lock (klass->image);
2375 if (!klass->methods) {
2376 klass->method.count = count;
2378 /* Needed because of the double-checking locking pattern */
2379 mono_memory_barrier ();
2381 klass->methods = methods;
2384 mono_image_unlock (klass->image);
2388 * mono_class_get_method_by_index:
2390 * Returns klass->methods [index], initializing klass->methods if neccesary.
2392 * LOCKING: Acquires the loader lock.
2395 mono_class_get_method_by_index (MonoClass *klass, int index)
2398 /* Avoid calling setup_methods () if possible */
2399 if (klass->generic_class && !klass->methods) {
2400 MonoClass *gklass = klass->generic_class->container_class;
2403 m = mono_class_inflate_generic_method_full_checked (
2404 gklass->methods [index], klass, mono_class_get_context (klass), &error);
2405 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2407 * If setup_methods () is called later for this class, no duplicates are created,
2408 * since inflate_generic_method guarantees that only one instance of a method
2409 * is created for each context.
2412 mono_class_setup_methods (klass);
2413 g_assert (m == klass->methods [index]);
2417 mono_class_setup_methods (klass);
2418 if (mono_class_has_failure (klass)) /*FIXME do proper error handling*/
2420 g_assert (index >= 0 && index < klass->method.count);
2421 return klass->methods [index];
2426 * mono_class_get_inflated_method:
2428 * Given an inflated class CLASS and a method METHOD which should be a method of
2429 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2432 mono_class_get_inflated_method (MonoClass *klass, MonoMethod *method)
2434 MonoClass *gklass = klass->generic_class->container_class;
2437 g_assert (method->klass == gklass);
2439 mono_class_setup_methods (gklass);
2440 g_assert (!mono_class_has_failure (gklass)); /*FIXME do proper error handling*/
2442 for (i = 0; i < gklass->method.count; ++i) {
2443 if (gklass->methods [i] == method) {
2444 if (klass->methods) {
2445 return klass->methods [i];
2448 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], klass, mono_class_get_context (klass), &error);
2449 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2459 * mono_class_get_vtable_entry:
2461 * Returns klass->vtable [offset], computing it if neccesary. Returns NULL on failure.
2462 * LOCKING: Acquires the loader lock.
2465 mono_class_get_vtable_entry (MonoClass *klass, int offset)
2469 if (klass->rank == 1) {
2471 * szarrays do not overwrite any methods of Array, so we can avoid
2472 * initializing their vtables in some cases.
2474 mono_class_setup_vtable (klass->parent);
2475 if (offset < klass->parent->vtable_size)
2476 return klass->parent->vtable [offset];
2479 if (klass->generic_class) {
2481 MonoClass *gklass = klass->generic_class->container_class;
2482 mono_class_setup_vtable (gklass);
2483 m = gklass->vtable [offset];
2485 m = mono_class_inflate_generic_method_full_checked (m, klass, mono_class_get_context (klass), &error);
2486 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2488 mono_class_setup_vtable (klass);
2489 if (mono_class_has_failure (klass))
2491 m = klass->vtable [offset];
2498 * mono_class_get_vtable_size:
2500 * Return the vtable size for KLASS.
2503 mono_class_get_vtable_size (MonoClass *klass)
2505 mono_class_setup_vtable (klass);
2507 return klass->vtable_size;
2511 * mono_class_setup_properties:
2513 * Initialize klass->ext.property and klass->ext.properties.
2515 * This method can fail the class.
2518 mono_class_setup_properties (MonoClass *klass)
2520 guint startm, endm, i, j;
2521 guint32 cols [MONO_PROPERTY_SIZE];
2522 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2523 MonoProperty *properties;
2527 if (klass->ext && klass->ext->properties)
2530 if (klass->generic_class) {
2531 MonoClass *gklass = klass->generic_class->container_class;
2533 mono_class_init (gklass);
2534 mono_class_setup_properties (gklass);
2535 if (mono_class_has_failure (gklass)) {
2536 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2540 properties = mono_class_new0 (klass, MonoProperty, gklass->ext->property.count + 1);
2542 for (i = 0; i < gklass->ext->property.count; i++) {
2544 MonoProperty *prop = &properties [i];
2546 *prop = gklass->ext->properties [i];
2549 prop->get = mono_class_inflate_generic_method_full_checked (
2550 prop->get, klass, mono_class_get_context (klass), &error);
2552 prop->set = mono_class_inflate_generic_method_full_checked (
2553 prop->set, klass, mono_class_get_context (klass), &error);
2555 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2556 prop->parent = klass;
2559 first = gklass->ext->property.first;
2560 count = gklass->ext->property.count;
2562 first = mono_metadata_properties_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2563 count = last - first;
2566 mono_class_setup_methods (klass);
2567 if (mono_class_has_failure (klass))
2571 properties = (MonoProperty *)mono_class_alloc0 (klass, sizeof (MonoProperty) * count);
2572 for (i = first; i < last; ++i) {
2573 mono_metadata_decode_table_row (klass->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2574 properties [i - first].parent = klass;
2575 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2576 properties [i - first].name = mono_metadata_string_heap (klass->image, cols [MONO_PROPERTY_NAME]);
2578 startm = mono_metadata_methods_from_property (klass->image, i, &endm);
2579 for (j = startm; j < endm; ++j) {
2582 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2584 if (klass->image->uncompressed_metadata) {
2586 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2587 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2588 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2590 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - klass->method.first];
2593 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2594 case METHOD_SEMANTIC_SETTER:
2595 properties [i - first].set = method;
2597 case METHOD_SEMANTIC_GETTER:
2598 properties [i - first].get = method;
2607 mono_class_alloc_ext (klass);
2609 mono_image_lock (klass->image);
2611 if (klass->ext->properties) {
2612 /* We leak 'properties' which was allocated from the image mempool */
2613 mono_image_unlock (klass->image);
2617 klass->ext->property.first = first;
2618 klass->ext->property.count = count;
2620 /* Flush any pending writes as we do double checked locking on klass->ext->properties */
2621 mono_memory_barrier ();
2623 /* Leave this assignment as the last op in the function */
2624 klass->ext->properties = properties;
2626 mono_image_unlock (klass->image);
2630 inflate_method_listz (MonoMethod **methods, MonoClass *klass, MonoGenericContext *context)
2632 MonoMethod **om, **retval;
2635 for (om = methods, count = 0; *om; ++om, ++count)
2638 retval = g_new0 (MonoMethod*, count + 1);
2640 for (om = methods, count = 0; *om; ++om, ++count) {
2642 retval [count] = mono_class_inflate_generic_method_full_checked (*om, klass, context, &error);
2643 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2649 /*This method can fail the class.*/
2651 mono_class_setup_events (MonoClass *klass)
2654 guint startm, endm, i, j;
2655 guint32 cols [MONO_EVENT_SIZE];
2656 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2660 if (klass->ext && klass->ext->events)
2663 if (klass->generic_class) {
2664 MonoClass *gklass = klass->generic_class->container_class;
2665 MonoGenericContext *context = NULL;
2667 mono_class_setup_events (gklass);
2668 if (mono_class_has_failure (gklass)) {
2669 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2673 first = gklass->ext->event.first;
2674 count = gklass->ext->event.count;
2676 events = mono_class_new0 (klass, MonoEvent, count);
2679 context = mono_class_get_context (klass);
2681 for (i = 0; i < count; i++) {
2683 MonoEvent *event = &events [i];
2684 MonoEvent *gevent = &gklass->ext->events [i];
2686 mono_error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2688 event->parent = klass;
2689 event->name = gevent->name;
2690 event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, klass, context, &error) : NULL;
2691 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2692 event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, klass, context, &error) : NULL;
2693 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2694 event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, klass, context, &error) : NULL;
2695 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2697 #ifndef MONO_SMALL_CONFIG
2698 event->other = gevent->other ? inflate_method_listz (gevent->other, klass, context) : NULL;
2700 event->attrs = gevent->attrs;
2703 first = mono_metadata_events_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2704 count = last - first;
2707 mono_class_setup_methods (klass);
2708 if (mono_class_has_failure (klass)) {
2709 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2714 events = (MonoEvent *)mono_class_alloc0 (klass, sizeof (MonoEvent) * count);
2715 for (i = first; i < last; ++i) {
2716 MonoEvent *event = &events [i - first];
2718 mono_metadata_decode_table_row (klass->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2719 event->parent = klass;
2720 event->attrs = cols [MONO_EVENT_FLAGS];
2721 event->name = mono_metadata_string_heap (klass->image, cols [MONO_EVENT_NAME]);
2723 startm = mono_metadata_methods_from_event (klass->image, i, &endm);
2724 for (j = startm; j < endm; ++j) {
2727 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2729 if (klass->image->uncompressed_metadata) {
2731 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2732 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2733 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2735 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - klass->method.first];
2738 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2739 case METHOD_SEMANTIC_ADD_ON:
2740 event->add = method;
2742 case METHOD_SEMANTIC_REMOVE_ON:
2743 event->remove = method;
2745 case METHOD_SEMANTIC_FIRE:
2746 event->raise = method;
2748 case METHOD_SEMANTIC_OTHER: {
2749 #ifndef MONO_SMALL_CONFIG
2752 if (event->other == NULL) {
2753 event->other = g_new0 (MonoMethod*, 2);
2755 while (event->other [n])
2757 event->other = (MonoMethod **)g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2759 event->other [n] = method;
2760 /* NULL terminated */
2761 event->other [n + 1] = NULL;
2772 mono_class_alloc_ext (klass);
2774 mono_image_lock (klass->image);
2776 if (klass->ext->events) {
2777 mono_image_unlock (klass->image);
2781 klass->ext->event.first = first;
2782 klass->ext->event.count = count;
2784 /* Flush any pending writes as we do double checked locking on klass->ext.events */
2785 mono_memory_barrier ();
2787 /* Leave this assignment as the last op in the function */
2788 klass->ext->events = events;
2790 mono_image_unlock (klass->image);
2794 * Global pool of interface IDs, represented as a bitset.
2795 * LOCKING: Protected by the classes lock.
2797 static MonoBitSet *global_interface_bitset = NULL;
2800 * mono_unload_interface_ids:
2801 * @bitset: bit set of interface IDs
2803 * When an image is unloaded, the interface IDs associated with
2804 * the image are put back in the global pool of IDs so the numbers
2808 mono_unload_interface_ids (MonoBitSet *bitset)
2811 mono_bitset_sub (global_interface_bitset, bitset);
2816 mono_unload_interface_id (MonoClass *klass)
2818 if (global_interface_bitset && klass->interface_id) {
2820 mono_bitset_clear (global_interface_bitset, klass->interface_id);
2826 * mono_get_unique_iid:
2829 * Assign a unique integer ID to the interface represented by @class.
2830 * The ID will positive and as small as possible.
2831 * LOCKING: Acquires the classes lock.
2832 * Returns: The new ID.
2835 mono_get_unique_iid (MonoClass *klass)
2839 g_assert (MONO_CLASS_IS_INTERFACE (klass));
2843 if (!global_interface_bitset) {
2844 global_interface_bitset = mono_bitset_new (128, 0);
2847 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2849 int old_size = mono_bitset_size (global_interface_bitset);
2850 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2851 mono_bitset_free (global_interface_bitset);
2852 global_interface_bitset = new_set;
2855 mono_bitset_set (global_interface_bitset, iid);
2856 /* set the bit also in the per-image set */
2857 if (!klass->generic_class) {
2858 if (klass->image->interface_bitset) {
2859 if (iid >= mono_bitset_size (klass->image->interface_bitset)) {
2860 MonoBitSet *new_set = mono_bitset_clone (klass->image->interface_bitset, iid + 1);
2861 mono_bitset_free (klass->image->interface_bitset);
2862 klass->image->interface_bitset = new_set;
2865 klass->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2867 mono_bitset_set (klass->image->interface_bitset, iid);
2872 #ifndef MONO_SMALL_CONFIG
2873 if (mono_print_vtable) {
2875 char *type_name = mono_type_full_name (&klass->byval_arg);
2876 if (klass->generic_class && !klass->generic_class->context.class_inst->is_open) {
2877 generic_id = klass->generic_class->context.class_inst->id;
2878 g_assert (generic_id != 0);
2882 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, klass->image->name, type_name, generic_id);
2887 g_assert (iid <= 65535);
2892 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2897 mono_class_setup_interfaces (klass, error);
2898 return_if_nok (error);
2900 for (i = 0; i < klass->interface_count; i++) {
2901 ic = klass->interfaces [i];
2904 *res = g_ptr_array_new ();
2905 g_ptr_array_add (*res, ic);
2906 mono_class_init (ic);
2907 if (mono_class_has_failure (ic)) {
2908 mono_error_set_type_load_class (error, ic, "Error Loading class");
2912 collect_implemented_interfaces_aux (ic, res, error);
2913 return_if_nok (error);
2918 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2920 GPtrArray *res = NULL;
2922 collect_implemented_interfaces_aux (klass, &res, error);
2923 if (!mono_error_ok (error)) {
2925 g_ptr_array_free (res, TRUE);
2932 compare_interface_ids (const void *p_key, const void *p_element) {
2933 const MonoClass *key = (const MonoClass *)p_key;
2934 const MonoClass *element = *(const MonoClass **)p_element;
2936 return (key->interface_id - element->interface_id);
2939 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2941 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2942 MonoClass **result = (MonoClass **)mono_binary_search (
2944 klass->interfaces_packed,
2945 klass->interface_offsets_count,
2946 sizeof (MonoClass *),
2947 compare_interface_ids);
2949 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2956 * mono_class_interface_offset_with_variance:
2958 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2959 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2961 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2963 * FIXME figure out MS disambiguation rules and fix this function.
2966 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2967 int i = mono_class_interface_offset (klass, itf);
2968 *non_exact_match = FALSE;
2972 if (!mono_class_has_variant_generic_params (itf))
2975 for (i = 0; i < klass->interface_offsets_count; i++) {
2976 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2977 *non_exact_match = TRUE;
2978 return klass->interface_offsets_packed [i];
2986 print_implemented_interfaces (MonoClass *klass) {
2989 GPtrArray *ifaces = NULL;
2991 int ancestor_level = 0;
2993 name = mono_type_get_full_name (klass);
2994 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2997 for (i = 0; i < klass->interface_offsets_count; i++)
2998 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2999 klass->interfaces_packed [i]->interface_id,
3000 klass->interface_offsets_packed [i],
3001 klass->interfaces_packed [i]->method.count,
3002 klass->interfaces_packed [i]->name_space,
3003 klass->interfaces_packed [i]->name );
3004 printf ("Interface flags: ");
3005 for (i = 0; i <= klass->max_interface_id; i++)
3006 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
3007 printf ("(%d,T)", i);
3009 printf ("(%d,F)", i);
3011 printf ("Dump interface flags:");
3012 #ifdef COMPRESSED_INTERFACE_BITMAP
3014 const uint8_t* p = klass->interface_bitmap;
3015 i = klass->max_interface_id;
3017 printf (" %d x 00 %02X", p [0], p [1]);
3023 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
3024 printf (" %02X", klass->interface_bitmap [i]);
3027 while (klass != NULL) {
3028 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
3029 ifaces = mono_class_get_implemented_interfaces (klass, &error);
3030 if (!mono_error_ok (&error)) {
3031 printf (" Type failed due to %s\n", mono_error_get_message (&error));
3032 mono_error_cleanup (&error);
3033 } else if (ifaces) {
3034 for (i = 0; i < ifaces->len; i++) {
3035 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3036 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
3037 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3039 mono_class_interface_offset (klass, ic),
3044 g_ptr_array_free (ifaces, TRUE);
3047 klass = klass->parent;
3052 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
3055 args [0] = &arg0->byval_arg;
3057 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
3061 array_class_get_if_rank (MonoClass *klass, guint rank)
3063 return rank ? mono_array_class_get (klass, rank) : klass;
3067 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
3069 valuetype_types [0] = eclass;
3070 if (eclass == mono_defaults.int16_class)
3071 valuetype_types [1] = mono_defaults.uint16_class;
3072 else if (eclass == mono_defaults.uint16_class)
3073 valuetype_types [1] = mono_defaults.int16_class;
3074 else if (eclass == mono_defaults.int32_class)
3075 valuetype_types [1] = mono_defaults.uint32_class;
3076 else if (eclass == mono_defaults.uint32_class)
3077 valuetype_types [1] = mono_defaults.int32_class;
3078 else if (eclass == mono_defaults.int64_class)
3079 valuetype_types [1] = mono_defaults.uint64_class;
3080 else if (eclass == mono_defaults.uint64_class)
3081 valuetype_types [1] = mono_defaults.int64_class;
3082 else if (eclass == mono_defaults.byte_class)
3083 valuetype_types [1] = mono_defaults.sbyte_class;
3084 else if (eclass == mono_defaults.sbyte_class)
3085 valuetype_types [1] = mono_defaults.byte_class;
3086 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
3087 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
3090 /* this won't be needed once bug #325495 is completely fixed
3091 * though we'll need something similar to know which interfaces to allow
3092 * in arrays when they'll be lazyly created
3094 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
3095 * MS returns diferrent types based on which instance is called. For example:
3096 * object obj = new byte[10][];
3097 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
3098 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
3101 * Fixing this should kill quite some code, save some bits and improve compatibility.
3104 get_implicit_generic_array_interfaces (MonoClass *klass, int *num, int *is_enumerator)
3106 MonoClass *eclass = klass->element_class;
3107 static MonoClass* generic_icollection_class = NULL;
3108 static MonoClass* generic_ienumerable_class = NULL;
3109 static MonoClass* generic_ienumerator_class = NULL;
3110 static MonoClass* generic_ireadonlylist_class = NULL;
3111 static MonoClass* generic_ireadonlycollection_class = NULL;
3112 MonoClass *valuetype_types[2] = { NULL, NULL };
3113 MonoClass **interfaces = NULL;
3114 int i, nifaces, interface_count, real_count, original_rank;
3116 gboolean internal_enumerator;
3117 gboolean eclass_is_valuetype;
3119 if (!mono_defaults.generic_ilist_class) {
3123 internal_enumerator = FALSE;
3124 eclass_is_valuetype = FALSE;
3125 original_rank = eclass->rank;
3126 if (klass->byval_arg.type != MONO_TYPE_SZARRAY) {
3127 if (klass->generic_class && klass->nested_in == mono_defaults.array_class && strcmp (klass->name, "InternalEnumerator`1") == 0) {
3129 * For a Enumerator<T[]> we need to get the list of interfaces for T.
3131 eclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
3132 original_rank = eclass->rank;
3134 eclass = eclass->element_class;
3135 internal_enumerator = TRUE;
3136 *is_enumerator = TRUE;
3144 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
3145 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
3147 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
3149 if (!generic_icollection_class) {
3150 generic_icollection_class = mono_class_load_from_name (mono_defaults.corlib,
3151 "System.Collections.Generic", "ICollection`1");
3152 generic_ienumerable_class = mono_class_load_from_name (mono_defaults.corlib,
3153 "System.Collections.Generic", "IEnumerable`1");
3154 generic_ienumerator_class = mono_class_load_from_name (mono_defaults.corlib,
3155 "System.Collections.Generic", "IEnumerator`1");
3156 generic_ireadonlylist_class = mono_class_load_from_name (mono_defaults.corlib,
3157 "System.Collections.Generic", "IReadOnlyList`1");
3158 generic_ireadonlycollection_class = mono_class_load_from_name (mono_defaults.corlib,
3159 "System.Collections.Generic", "IReadOnlyCollection`1");
3162 mono_class_init (eclass);
3165 * Arrays in 2.0 need to implement a number of generic interfaces
3166 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
3167 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
3168 * We collect the types needed to build the
3169 * instantiations in interfaces at intervals of 3/5, because 3/5 are
3170 * the generic interfaces needed to implement.
3172 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
3173 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
3175 if (eclass->valuetype) {
3176 nifaces = generic_ireadonlylist_class ? 5 : 3;
3177 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
3179 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
3180 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
3181 if (internal_enumerator) {
3183 if (valuetype_types [1])
3187 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3188 interfaces [0] = valuetype_types [0];
3189 if (valuetype_types [1])
3190 interfaces [nifaces] = valuetype_types [1];
3192 eclass_is_valuetype = TRUE;
3195 int idepth = eclass->idepth;
3196 if (!internal_enumerator)
3198 nifaces = generic_ireadonlylist_class ? 2 : 3;
3200 // FIXME: This doesn't seem to work/required for generic params
3201 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
3202 mono_class_setup_interface_offsets (eclass);
3204 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
3205 /* we add object for interfaces and the supertypes for the other
3206 * types. The last of the supertypes is the element class itself which we
3207 * already created the explicit interfaces for (so we include it for IEnumerator
3208 * and exclude it for arrays).
3210 if (MONO_CLASS_IS_INTERFACE (eclass))
3213 interface_count += idepth;
3214 if (eclass->rank && eclass->element_class->valuetype) {
3215 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3216 if (valuetype_types [1])
3219 /* IList, ICollection, IEnumerable, IReadOnlyList */
3220 interface_count *= nifaces;
3221 real_count = interface_count;
3222 if (internal_enumerator) {
3223 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3224 if (valuetype_types [1])
3227 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3228 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3229 interfaces [0] = mono_defaults.object_class;
3233 for (i = 0; i < idepth; i++) {
3234 mono_class_init (eclass->supertypes [i]);
3235 interfaces [j] = eclass->supertypes [i];
3239 if (all_interfaces) {
3240 for (i = 0; i < eclass->interface_offsets_count; i++) {
3241 interfaces [j] = eclass->interfaces_packed [i];
3245 for (i = 0; i < eclass->interface_count; i++) {
3246 interfaces [j] = eclass->interfaces [i];
3250 if (valuetype_types [1]) {
3251 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3256 /* instantiate the generic interfaces */
3257 for (i = 0; i < interface_count; i += nifaces) {
3258 MonoClass *iface = interfaces [i];
3260 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3261 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3263 if (eclass->valuetype) {
3264 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3265 if (generic_ireadonlylist_class) {
3266 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3267 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3270 if (!generic_ireadonlylist_class)
3271 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3274 if (internal_enumerator) {
3276 /* instantiate IEnumerator<iface> */
3277 for (i = 0; i < interface_count; i++) {
3278 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3280 j = interface_count;
3281 if (!eclass_is_valuetype) {
3282 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3283 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3286 for (i = 0; i < eclass->idepth; i++) {
3287 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3291 for (i = 0; i < eclass->interface_offsets_count; i++) {
3292 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3296 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3298 if (valuetype_types [1])
3299 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3303 char *type_name = mono_type_get_name_full (&klass->byval_arg, 0);
3304 for (i = 0; i < real_count; ++i) {
3305 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3306 g_print ("%s implements %s\n", type_name, name);
3317 find_array_interface (MonoClass *klass, const char *name)
3320 for (i = 0; i < klass->interface_count; ++i) {
3321 if (strcmp (klass->interfaces [i]->name, name) == 0)
3328 * Return the number of virtual methods.
3329 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3330 * Return -1 on failure.
3331 * FIXME It would be nice if this information could be cached somewhere.
3334 count_virtual_methods (MonoClass *klass)
3338 klass = mono_class_get_generic_type_definition (klass); /*We can find this information by looking at the GTD*/
3340 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
3341 mono_class_setup_methods (klass);
3342 if (mono_class_has_failure (klass))
3345 for (i = 0; i < klass->method.count; ++i) {
3346 flags = klass->methods [i]->flags;
3347 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3351 for (i = 0; i < klass->method.count; ++i) {
3352 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
3354 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3362 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3370 m = (l + num_ifaces) / 2;
3371 if (interfaces_full [m] == ic)
3373 if (l == num_ifaces)
3375 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3384 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3386 int i = find_interface (num_ifaces, interfaces_full, ic);
3388 return interface_offsets_full [i];
3393 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3395 int i = find_interface (num_ifaces, interfaces_full, ic);
3399 interface_offsets_full [i] = offset;
3402 for (i = 0; i < num_ifaces; ++i) {
3403 if (interfaces_full [i]) {
3405 if (interfaces_full [i]->interface_id < ic->interface_id)
3408 while (end < num_ifaces && interfaces_full [end]) end++;
3409 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3410 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3412 interfaces_full [i] = ic;
3413 interface_offsets_full [i] = offset;
3419 #ifdef COMPRESSED_INTERFACE_BITMAP
3422 * Compressed interface bitmap design.
3424 * Interface bitmaps take a large amount of memory, because their size is
3425 * linear with the maximum interface id assigned in the process (each interface
3426 * is assigned a unique id as it is loaded). The number of interface classes
3427 * is high because of the many implicit interfaces implemented by arrays (we'll
3428 * need to lazy-load them in the future).
3429 * Most classes implement a very small number of interfaces, so the bitmap is
3430 * sparse. This bitmap needs to be checked by interface casts, so access to the
3431 * needed bit must be fast and doable with few jit instructions.
3433 * The current compression format is as follows:
3434 * *) it is a sequence of one or more two-byte elements
3435 * *) the first byte in the element is the count of empty bitmap bytes
3436 * at the current bitmap position
3437 * *) the second byte in the element is an actual bitmap byte at the current
3440 * As an example, the following compressed bitmap bytes:
3441 * 0x07 0x01 0x00 0x7
3442 * correspond to the following bitmap:
3443 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3445 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3446 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3447 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3451 * mono_compress_bitmap:
3452 * @dest: destination buffer
3453 * @bitmap: bitmap buffer
3454 * @size: size of @bitmap in bytes
3456 * This is a mono internal function.
3457 * The @bitmap data is compressed into a format that is small but
3458 * still searchable in few instructions by the JIT and runtime.
3459 * The compressed data is stored in the buffer pointed to by the
3460 * @dest array. Passing a #NULL value for @dest allows to just compute
3461 * the size of the buffer.
3462 * This compression algorithm assumes the bits set in the bitmap are
3463 * few and far between, like in interface bitmaps.
3464 * Returns: The size of the compressed bitmap in bytes.
3467 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3471 const uint8_t *end = bitmap + size;
3472 while (bitmap < end) {
3473 if (*bitmap || numz == 255) {
3497 * mono_class_interface_match:
3498 * @bitmap: a compressed bitmap buffer
3499 * @id: the index to check in the bitmap
3501 * This is a mono internal function.
3502 * Checks if a bit is set in a compressed interface bitmap. @id must
3503 * be already checked for being smaller than the maximum id encoded in the
3506 * Returns: A non-zero value if bit @id is set in the bitmap @bitmap,
3510 mono_class_interface_match (const uint8_t *bitmap, int id)
3513 id -= bitmap [0] * 8;
3517 return bitmap [1] & (1 << id);
3526 * LOCKING: this is supposed to be called with the loader lock held.
3527 * Return -1 on failure and set exception_type
3530 setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite)
3534 int i, j, max_iid, num_ifaces;
3535 MonoClass **interfaces_full = NULL;
3536 int *interface_offsets_full = NULL;
3538 GPtrArray **ifaces_array = NULL;
3539 int interface_offsets_count;
3540 MonoClass **array_interfaces = NULL;
3541 int num_array_interfaces;
3542 int is_enumerator = FALSE;
3544 mono_class_setup_supertypes (klass);
3546 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3547 * implicit interfaces have the property that they are assigned the same slot in the
3548 * vtables for compatible interfaces
3550 array_interfaces = get_implicit_generic_array_interfaces (klass, &num_array_interfaces, &is_enumerator);
3552 /* compute maximum number of slots and maximum interface id */
3554 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3555 ifaces_array = g_new0 (GPtrArray *, klass->idepth);
3556 for (j = 0; j < klass->idepth; j++) {
3557 k = klass->supertypes [j];
3558 num_ifaces += k->interface_count;
3559 for (i = 0; i < k->interface_count; i++) {
3560 ic = k->interfaces [i];
3563 mono_class_init (ic);
3565 if (max_iid < ic->interface_id)
3566 max_iid = ic->interface_id;
3568 ifaces = mono_class_get_implemented_interfaces (k, &error);
3569 if (!mono_error_ok (&error)) {
3570 char *name = mono_type_get_full_name (k);
3571 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)));
3573 mono_error_cleanup (&error);
3578 num_ifaces += ifaces->len;
3579 for (i = 0; i < ifaces->len; ++i) {
3580 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3581 if (max_iid < ic->interface_id)
3582 max_iid = ic->interface_id;
3584 ifaces_array [j] = ifaces;
3588 for (i = 0; i < num_array_interfaces; ++i) {
3589 ic = array_interfaces [i];
3590 mono_class_init (ic);
3591 if (max_iid < ic->interface_id)
3592 max_iid = ic->interface_id;
3595 if (MONO_CLASS_IS_INTERFACE (klass)) {
3597 if (max_iid < klass->interface_id)
3598 max_iid = klass->interface_id;
3600 klass->max_interface_id = max_iid;
3601 /* compute vtable offset for interfaces */
3602 interfaces_full = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3603 interface_offsets_full = (int *)g_malloc (sizeof (int) * num_ifaces);
3605 for (i = 0; i < num_ifaces; i++) {
3606 interface_offsets_full [i] = -1;
3609 /* skip the current class */
3610 for (j = 0; j < klass->idepth - 1; j++) {
3611 k = klass->supertypes [j];
3612 ifaces = ifaces_array [j];
3615 for (i = 0; i < ifaces->len; ++i) {
3617 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3619 /*Force the sharing of interface offsets between parent and subtypes.*/
3620 io = mono_class_interface_offset (k, ic);
3622 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3627 g_assert (klass == klass->supertypes [klass->idepth - 1]);
3628 ifaces = ifaces_array [klass->idepth - 1];
3630 for (i = 0; i < ifaces->len; ++i) {
3632 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3633 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3635 count = count_virtual_methods (ic);
3637 char *name = mono_type_get_full_name (ic);
3638 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error calculating interface offset of %s", name));
3647 if (MONO_CLASS_IS_INTERFACE (klass))
3648 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, klass, cur_slot, TRUE);
3650 if (num_array_interfaces) {
3651 if (is_enumerator) {
3652 int ienumerator_idx = find_array_interface (klass, "IEnumerator`1");
3653 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ienumerator_idx]);
3654 g_assert (ienumerator_offset >= 0);
3655 for (i = 0; i < num_array_interfaces; ++i) {
3656 ic = array_interfaces [i];
3657 if (strcmp (ic->name, "IEnumerator`1") == 0)
3658 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3660 g_assert_not_reached ();
3661 /*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);*/
3664 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3665 int ilist_iface_idx = find_array_interface (klass, "IList`1");
3666 MonoClass* ilist_class = klass->interfaces [ilist_iface_idx];
3667 int ireadonlylist_iface_idx = find_array_interface (klass, "IReadOnlyList`1");
3668 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? klass->interfaces [ireadonlylist_iface_idx] : NULL;
3669 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3670 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3671 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3672 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ilist_iface_idx]);
3673 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3674 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3675 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ireadonlylist_iface_idx]) : -1;
3676 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3677 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3678 for (i = 0; i < num_array_interfaces; ++i) {
3680 ic = array_interfaces [i];
3681 if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
3682 offset = ilist_offset;
3683 else if (strcmp (ic->name, "ICollection`1") == 0)
3684 offset = icollection_offset;
3685 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3686 offset = ienumerable_offset;
3687 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3688 offset = ireadonlylist_offset;
3689 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3690 offset = ireadonlycollection_offset;
3692 g_assert_not_reached ();
3693 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3694 /*g_print ("type %s has %s offset at %d (%s)\n", klass->name, ic->name, offset, klass->interfaces [0]->name);*/
3699 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3700 if (interface_offsets_full [i] != -1) {
3701 interface_offsets_count ++;
3706 * We might get called multiple times:
3707 * - mono_class_init ()
3708 * - mono_class_setup_vtable ().
3709 * - mono_class_setup_interface_offsets ().
3710 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3711 * means we have to overwrite those when called from other places (#4440).
3713 if (klass->interfaces_packed) {
3715 g_assert (klass->interface_offsets_count == interface_offsets_count);
3719 klass->interface_offsets_count = interface_offsets_count;
3720 klass->interfaces_packed = (MonoClass **)mono_class_alloc (klass, sizeof (MonoClass*) * interface_offsets_count);
3721 klass->interface_offsets_packed = (guint16 *)mono_class_alloc (klass, sizeof (guint16) * interface_offsets_count);
3722 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3723 #ifdef COMPRESSED_INTERFACE_BITMAP
3724 bitmap = g_malloc0 (bsize);
3726 bitmap = (uint8_t *)mono_class_alloc0 (klass, bsize);
3728 for (i = 0; i < interface_offsets_count; i++) {
3729 int id = interfaces_full [i]->interface_id;
3730 bitmap [id >> 3] |= (1 << (id & 7));
3731 klass->interfaces_packed [i] = interfaces_full [i];
3732 klass->interface_offsets_packed [i] = interface_offsets_full [i];
3733 /*if (num_array_interfaces)
3734 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]);*/
3736 #ifdef COMPRESSED_INTERFACE_BITMAP
3737 i = mono_compress_bitmap (NULL, bitmap, bsize);
3738 klass->interface_bitmap = mono_class_alloc0 (klass, i);
3739 mono_compress_bitmap (klass->interface_bitmap, bitmap, bsize);
3742 klass->interface_bitmap = bitmap;
3747 g_free (interfaces_full);
3748 g_free (interface_offsets_full);
3749 g_free (array_interfaces);
3750 for (i = 0; i < klass->idepth; i++) {
3751 ifaces = ifaces_array [i];
3753 g_ptr_array_free (ifaces, TRUE);
3755 g_free (ifaces_array);
3757 //printf ("JUST DONE: ");
3758 //print_implemented_interfaces (klass);
3764 * Setup interface offsets for interfaces.
3766 * - klass->max_interface_id
3767 * - klass->interface_offsets_count
3768 * - klass->interfaces_packed
3769 * - klass->interface_offsets_packed
3770 * - klass->interface_bitmap
3772 * This function can fail @class.
3775 mono_class_setup_interface_offsets (MonoClass *klass)
3777 mono_loader_lock ();
3779 setup_interface_offsets (klass, 0, FALSE);
3781 mono_loader_unlock ();
3784 /*Checks if @klass has @parent as one of it's parents type gtd
3788 * Bar<T> : Foo<Bar<Bar<T>>>
3792 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3794 klass = mono_class_get_generic_type_definition (klass);
3795 parent = mono_class_get_generic_type_definition (parent);
3796 mono_class_setup_supertypes (klass);
3797 mono_class_setup_supertypes (parent);
3799 return klass->idepth >= parent->idepth &&
3800 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3804 mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup)
3806 MonoGenericInst *ginst;
3808 if (!klass->generic_class) {
3809 mono_class_setup_vtable_full (klass, in_setup);
3810 return !mono_class_has_failure (klass);
3813 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup);
3814 if (mono_class_has_failure (klass->generic_class->container_class)) {
3815 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to load generic definition vtable"));
3819 ginst = klass->generic_class->context.class_inst;
3820 for (i = 0; i < ginst->type_argc; ++i) {
3822 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3824 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3825 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3826 if (mono_class_has_gtd_parent (klass, arg) || mono_class_has_gtd_parent (arg, klass))
3828 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3829 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Failed to load generic parameter %d", i));
3837 * mono_class_setup_vtable:
3839 * Creates the generic vtable of CLASS.
3840 * Initializes the following fields in MonoClass:
3843 * Plus all the fields initialized by setup_interface_offsets ().
3844 * If there is an error during vtable construction, klass->exception_type is set.
3846 * LOCKING: Acquires the loader lock.
3849 mono_class_setup_vtable (MonoClass *klass)
3851 mono_class_setup_vtable_full (klass, NULL);
3855 mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
3858 MonoMethod **overrides;
3859 MonoGenericContext *context;
3867 if (MONO_CLASS_IS_INTERFACE (klass)) {
3868 /* This sets method->slot for all methods if this is an interface */
3869 mono_class_setup_methods (klass);
3873 if (mono_class_has_failure (klass))
3876 if (g_list_find (in_setup, klass))
3879 mono_loader_lock ();
3881 if (klass->vtable) {
3882 mono_loader_unlock ();
3886 mono_stats.generic_vtable_count ++;
3887 in_setup = g_list_prepend (in_setup, klass);
3889 if (klass->generic_class) {
3890 if (!mono_class_check_vtable_constraints (klass, in_setup)) {
3891 mono_loader_unlock ();
3892 g_list_remove (in_setup, klass);
3896 context = mono_class_get_context (klass);
3897 type_token = klass->generic_class->container_class->type_token;
3899 context = (MonoGenericContext *) klass->generic_container;
3900 type_token = klass->type_token;
3903 if (image_is_dynamic (klass->image)) {
3904 /* Generic instances can have zero method overrides without causing any harm.
3905 * This is true since we don't do layout all over again for them, we simply inflate
3906 * the layout of the parent.
3908 mono_reflection_get_dynamic_overrides (klass, &overrides, &onum, &error);
3909 if (!is_ok (&error)) {
3910 mono_loader_unlock ();
3911 g_list_remove (in_setup, klass);
3912 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)));
3913 mono_error_cleanup (&error);
3917 /* The following call fails if there are missing methods in the type */
3918 /* FIXME it's probably a good idea to avoid this for generic instances. */
3919 ok = mono_class_get_overrides_full (klass->image, type_token, &overrides, &onum, context);
3923 mono_class_setup_vtable_general (klass, overrides, onum, in_setup);
3925 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load list of method overrides"));
3929 mono_loader_unlock ();
3930 g_list_remove (in_setup, klass);
3935 #define DEBUG_INTERFACE_VTABLE_CODE 0
3936 #define TRACE_INTERFACE_VTABLE_CODE 0
3937 #define VERIFY_INTERFACE_VTABLE_CODE 0
3938 #define VTABLE_SELECTOR (1)
3940 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3941 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3942 if (!(VTABLE_SELECTOR)) break; \
3946 #define DEBUG_INTERFACE_VTABLE(stmt)
3949 #if TRACE_INTERFACE_VTABLE_CODE
3950 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3951 if (!(VTABLE_SELECTOR)) break; \
3955 #define TRACE_INTERFACE_VTABLE(stmt)
3958 #if VERIFY_INTERFACE_VTABLE_CODE
3959 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3960 if (!(VTABLE_SELECTOR)) break; \
3964 #define VERIFY_INTERFACE_VTABLE(stmt)
3968 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3970 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3974 GString *res = g_string_new ("");
3976 g_string_append_c (res, '(');
3977 for (i = 0; i < sig->param_count; ++i) {
3979 g_string_append_c (res, ',');
3980 mono_type_get_desc (res, sig->params [i], include_namespace);
3982 g_string_append (res, ")=>");
3983 if (sig->ret != NULL) {
3984 mono_type_get_desc (res, sig->ret, include_namespace);
3986 g_string_append (res, "NULL");
3989 g_string_free (res, FALSE);
3993 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3994 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3995 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3996 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
4004 is_wcf_hack_disabled (void)
4006 static gboolean disabled;
4007 static gboolean inited = FALSE;
4009 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
4016 check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
4018 MonoMethodSignature *cmsig, *imsig;
4019 if (strcmp (im->name, cm->name) == 0) {
4020 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
4021 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
4024 if (! slot_is_empty) {
4025 if (require_newslot) {
4026 if (! interface_is_explicitly_implemented_by_class) {
4027 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
4030 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4031 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
4035 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
4038 cmsig = mono_method_signature (cm);
4039 imsig = mono_method_signature (im);
4040 if (!cmsig || !imsig) {
4041 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
4045 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4046 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
4047 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4048 TRACE_INTERFACE_VTABLE (printf ("]"));
4051 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
4052 if (mono_security_core_clr_enabled ())
4053 mono_security_core_clr_check_override (klass, cm, im);
4055 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
4056 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4057 char *body_name = mono_method_full_name (cm, TRUE);
4058 char *decl_name = mono_method_full_name (im, TRUE);
4059 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));
4067 MonoClass *ic = im->klass;
4068 const char *ic_name_space = ic->name_space;
4069 const char *ic_name = ic->name;
4072 if (! require_newslot) {
4073 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
4076 if (cm->klass->rank == 0) {
4077 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
4080 cmsig = mono_method_signature (cm);
4081 imsig = mono_method_signature (im);
4082 if (!cmsig || !imsig) {
4083 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
4087 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4088 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
4089 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4090 TRACE_INTERFACE_VTABLE (printf ("]"));
4093 if (mono_class_get_image (ic) != mono_defaults.corlib) {
4094 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
4097 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
4098 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
4101 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))) {
4102 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
4106 subname = strstr (cm->name, ic_name_space);
4107 if (subname != cm->name) {
4108 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
4111 subname += strlen (ic_name_space);
4112 if (subname [0] != '.') {
4113 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
4117 if (strstr (subname, ic_name) != subname) {
4118 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
4121 subname += strlen (ic_name);
4122 if (subname [0] != '.') {
4123 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
4127 if (strcmp (subname, im->name) != 0) {
4128 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
4132 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
4133 if (mono_security_core_clr_enabled ())
4134 mono_security_core_clr_check_override (klass, cm, im);
4136 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
4137 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4138 char *body_name = mono_method_full_name (cm, TRUE);
4139 char *decl_name = mono_method_full_name (im, TRUE);
4140 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));
4150 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
4152 foreach_override (gpointer key, gpointer value, gpointer user_data) {
4153 MonoMethod *method = key;
4154 MonoMethod *override = value;
4155 MonoClass *method_class = mono_method_get_class (method);
4156 MonoClass *override_class = mono_method_get_class (override);
4158 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
4159 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
4160 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
4163 print_overrides (GHashTable *override_map, const char *message) {
4165 printf ("Override map \"%s\" START:\n", message);
4166 g_hash_table_foreach (override_map, foreach_override, NULL);
4167 printf ("Override map \"%s\" END.\n", message);
4169 printf ("Override map \"%s\" EMPTY.\n", message);
4173 print_vtable_full (MonoClass *klass, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
4174 char *full_name = mono_type_full_name (&klass->byval_arg);
4178 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
4180 if (print_interfaces) {
4181 print_implemented_interfaces (klass);
4182 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
4185 if (klass->parent) {
4186 parent_size = klass->parent->vtable_size;
4190 for (i = 0; i < size; ++i) {
4191 MonoMethod *cm = vtable [i];
4192 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
4193 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
4195 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
4203 #if VERIFY_INTERFACE_VTABLE_CODE
4205 mono_method_try_get_vtable_index (MonoMethod *method)
4207 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4208 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4209 if (imethod->declaring->is_generic)
4210 return imethod->declaring->slot;
4212 return method->slot;
4216 mono_class_verify_vtable (MonoClass *klass)
4219 char *full_name = mono_type_full_name (&klass->byval_arg);
4221 printf ("*** Verifying VTable of class '%s' \n", full_name);
4225 if (!klass->methods)
4228 for (i = 0; i < klass->method.count; ++i) {
4229 MonoMethod *cm = klass->methods [i];
4232 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4236 full_name = mono_method_full_name (cm, TRUE);
4238 slot = mono_method_try_get_vtable_index (cm);
4240 if (slot >= klass->vtable_size) {
4241 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, klass->vtable_size);
4245 if (slot >= 0 && klass->vtable [slot] != cm && (klass->vtable [slot])) {
4246 char *other_name = klass->vtable [slot] ? mono_method_full_name (klass->vtable [slot], TRUE) : g_strdup ("[null value]");
4247 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4248 g_free (other_name);
4251 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4258 print_unimplemented_interface_method_info (MonoClass *klass, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4260 char *method_signature;
4263 for (index = 0; index < onum; ++index) {
4264 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4265 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4267 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4268 type_name = mono_type_full_name (&klass->byval_arg);
4269 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4270 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4271 g_free (method_signature);
4273 mono_class_setup_methods (klass);
4274 if (mono_class_has_failure (klass)) {
4275 char *name = mono_type_get_full_name (klass);
4276 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4280 for (index = 0; index < klass->method.count; ++index) {
4281 MonoMethod *cm = klass->methods [index];
4282 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4284 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4285 g_free (method_signature);
4290 mono_method_get_method_definition (MonoMethod *method)
4292 while (method->is_inflated)
4293 method = ((MonoMethodInflated*)method)->declaring;
4298 verify_class_overrides (MonoClass *klass, MonoMethod **overrides, int onum)
4302 for (i = 0; i < onum; ++i) {
4303 MonoMethod *decl = overrides [i * 2];
4304 MonoMethod *body = overrides [i * 2 + 1];
4306 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (klass)) {
4307 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method belongs to a different class than the declared one"));
4311 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4312 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4313 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must not be static to override a base type"));
4315 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must be virtual to override a base type"));
4319 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4320 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4321 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a static method in a base type"));
4323 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a non virtual method in a base type"));
4327 if (!mono_class_is_assignable_from_slow (decl->klass, klass)) {
4328 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"));
4332 body = mono_method_get_method_definition (body);
4333 decl = mono_method_get_method_definition (decl);
4335 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4336 char *body_name = mono_method_full_name (body, TRUE);
4337 char *decl_name = mono_method_full_name (decl, TRUE);
4338 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));
4348 mono_class_need_stelemref_method (MonoClass *klass)
4350 return klass->rank == 1 && MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg);
4354 * LOCKING: this is supposed to be called with the loader lock held.
4357 mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int onum, GList *in_setup)
4361 MonoMethod **vtable;
4362 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4363 GPtrArray *ifaces = NULL;
4364 GHashTable *override_map = NULL;
4366 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4367 int first_non_interface_slot;
4369 GSList *virt_methods = NULL, *l;
4370 int stelemref_slot = 0;
4375 if (overrides && !verify_class_overrides (klass, overrides, onum))
4378 ifaces = mono_class_get_implemented_interfaces (klass, &error);
4379 if (!mono_error_ok (&error)) {
4380 char *name = mono_type_get_full_name (klass);
4381 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)));
4383 mono_error_cleanup (&error);
4385 } else if (ifaces) {
4386 for (i = 0; i < ifaces->len; i++) {
4387 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
4388 max_vtsize += ic->method.count;
4390 g_ptr_array_free (ifaces, TRUE);
4394 if (klass->parent) {
4395 mono_class_init (klass->parent);
4396 mono_class_setup_vtable_full (klass->parent, in_setup);
4398 if (mono_class_has_failure (klass->parent)) {
4399 char *name = mono_type_get_full_name (klass->parent);
4400 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Parent %s failed to load", name));
4405 max_vtsize += klass->parent->vtable_size;
4406 cur_slot = klass->parent->vtable_size;
4409 max_vtsize += klass->method.count;
4411 /*Array have a slot for stelemref*/
4412 if (mono_class_need_stelemref_method (klass)) {
4413 stelemref_slot = cur_slot;
4418 vtable = (MonoMethod **)alloca (sizeof (gpointer) * max_vtsize);
4419 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4421 /* printf ("METAINIT %s.%s\n", klass->name_space, klass->name); */
4423 cur_slot = setup_interface_offsets (klass, cur_slot, TRUE);
4424 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4427 max_iid = klass->max_interface_id;
4428 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4430 /* Optimized version for generic instances */
4431 if (klass->generic_class) {
4433 MonoClass *gklass = klass->generic_class->container_class;
4436 mono_class_setup_vtable_full (gklass, in_setup);
4437 if (mono_class_has_failure (gklass)) {
4438 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
4442 tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * gklass->vtable_size);
4443 klass->vtable_size = gklass->vtable_size;
4444 for (i = 0; i < gklass->vtable_size; ++i)
4445 if (gklass->vtable [i]) {
4446 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], klass, mono_class_get_context (klass), &error);
4447 if (!mono_error_ok (&error)) {
4448 char *err_msg = g_strdup_printf ("Could not inflate method due to %s", mono_error_get_message (&error));
4449 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
4451 mono_error_cleanup (&error);
4455 tmp [i]->slot = gklass->vtable [i]->slot;
4457 mono_memory_barrier ();
4458 klass->vtable = tmp;
4460 /* Have to set method->slot for abstract virtual methods */
4461 if (klass->methods && gklass->methods) {
4462 for (i = 0; i < klass->method.count; ++i)
4463 if (klass->methods [i]->slot == -1)
4464 klass->methods [i]->slot = gklass->methods [i]->slot;
4470 if (klass->parent && klass->parent->vtable_size) {
4471 MonoClass *parent = klass->parent;
4474 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4476 // Also inherit parent interface vtables, just as a starting point.
4477 // This is needed otherwise bug-77127.exe fails when the property methods
4478 // have different names in the iterface and the class, because for child
4479 // classes the ".override" information is not used anymore.
4480 for (i = 0; i < parent->interface_offsets_count; i++) {
4481 MonoClass *parent_interface = parent->interfaces_packed [i];
4482 int interface_offset = mono_class_interface_offset (klass, parent_interface);
4483 /*FIXME this is now dead code as this condition will never hold true.
4484 Since interface offsets are inherited then the offset of an interface implemented
4485 by a parent will never be the out of it's vtable boundary.
4487 if (interface_offset >= parent->vtable_size) {
4488 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4491 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4492 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4493 for (j = 0; j < parent_interface->method.count && !mono_class_has_failure (klass); j++) {
4494 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4495 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4496 parent_interface_offset + j, parent_interface_offset, j,
4497 interface_offset + j, interface_offset, j));
4504 /*Array have a slot for stelemref*/
4505 if (mono_class_need_stelemref_method (klass)) {
4506 MonoMethod *method = mono_marshal_get_virtual_stelemref (klass);
4508 method->slot = stelemref_slot;
4510 g_assert (method->slot == stelemref_slot);
4512 vtable [stelemref_slot] = method;
4515 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4516 /* override interface methods */
4517 for (i = 0; i < onum; i++) {
4518 MonoMethod *decl = overrides [i*2];
4519 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4521 dslot = mono_method_get_vtable_slot (decl);
4523 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
4527 dslot += mono_class_interface_offset (klass, decl->klass);
4528 vtable [dslot] = overrides [i*2 + 1];
4529 vtable [dslot]->slot = dslot;
4531 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4533 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4535 if (mono_security_core_clr_enabled ())
4536 mono_security_core_clr_check_override (klass, vtable [dslot], decl);
4539 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4540 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4543 * Create a list of virtual methods to avoid calling
4544 * mono_class_get_virtual_methods () which is slow because of the metadata
4548 gpointer iter = NULL;
4551 virt_methods = NULL;
4552 while ((cm = mono_class_get_virtual_methods (klass, &iter))) {
4553 virt_methods = g_slist_prepend (virt_methods, cm);
4555 if (mono_class_has_failure (klass))
4559 // Loop on all implemented interfaces...
4560 for (i = 0; i < klass->interface_offsets_count; i++) {
4561 MonoClass *parent = klass->parent;
4563 gboolean interface_is_explicitly_implemented_by_class;
4566 ic = klass->interfaces_packed [i];
4567 ic_offset = mono_class_interface_offset (klass, ic);
4569 mono_class_setup_methods (ic);
4570 if (mono_class_has_failure (ic))
4573 // Check if this interface is explicitly implemented (instead of just inherited)
4574 if (parent != NULL) {
4575 int implemented_interfaces_index;
4576 interface_is_explicitly_implemented_by_class = FALSE;
4577 for (implemented_interfaces_index = 0; implemented_interfaces_index < klass->interface_count; implemented_interfaces_index++) {
4578 if (ic == klass->interfaces [implemented_interfaces_index]) {
4579 interface_is_explicitly_implemented_by_class = TRUE;
4584 interface_is_explicitly_implemented_by_class = TRUE;
4587 // Loop on all interface methods...
4588 for (im_index = 0; im_index < ic->method.count; im_index++) {
4589 MonoMethod *im = ic->methods [im_index];
4590 int im_slot = ic_offset + im->slot;
4591 MonoMethod *override_im = (override_map != NULL) ? (MonoMethod *)g_hash_table_lookup (override_map, im) : NULL;
4593 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4596 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4598 // If there is an explicit implementation, just use it right away,
4599 // otherwise look for a matching method
4600 if (override_im == NULL) {
4604 // First look for a suitable method among the class methods
4605 for (l = virt_methods; l; l = l->next) {
4606 cm = (MonoMethod *)l->data;
4607 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)));
4608 if (check_interface_method_override (klass, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
4609 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4610 vtable [im_slot] = cm;
4611 /* Why do we need this? */
4616 TRACE_INTERFACE_VTABLE (printf ("\n"));
4617 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4621 // If the slot is still empty, look in all the inherited virtual methods...
4622 if ((vtable [im_slot] == NULL) && klass->parent != NULL) {
4623 MonoClass *parent = klass->parent;
4624 // Reverse order, so that last added methods are preferred
4625 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4626 MonoMethod *cm = parent->vtable [cm_index];
4628 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));
4629 if ((cm != NULL) && check_interface_method_override (klass, im, cm, FALSE, FALSE, TRUE)) {
4630 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4631 vtable [im_slot] = cm;
4632 /* Why do we need this? */
4638 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4640 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4644 g_assert (vtable [im_slot] == override_im);
4649 // If the class is not abstract, check that all its interface slots are full.
4650 // The check is done here and not directly at the end of the loop above because
4651 // it can happen (for injected generic array interfaces) that the same slot is
4652 // processed multiple times (those interfaces have overlapping slots), and it
4653 // will not always be the first pass the one that fills the slot.
4654 if (! (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4655 for (i = 0; i < klass->interface_offsets_count; i++) {
4659 ic = klass->interfaces_packed [i];
4660 ic_offset = mono_class_interface_offset (klass, ic);
4662 for (im_index = 0; im_index < ic->method.count; im_index++) {
4663 MonoMethod *im = ic->methods [im_index];
4664 int im_slot = ic_offset + im->slot;
4666 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4669 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4670 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4671 if (vtable [im_slot] == NULL) {
4672 print_unimplemented_interface_method_info (klass, ic, im, im_slot, overrides, onum);
4679 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4680 for (l = virt_methods; l; l = l->next) {
4681 cm = (MonoMethod *)l->data;
4683 * If the method is REUSE_SLOT, we must check in the
4684 * base class for a method to override.
4686 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4688 for (k = klass->parent; k ; k = k->parent) {
4693 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4694 MonoMethodSignature *cmsig, *m1sig;
4696 cmsig = mono_method_signature (cm);
4697 m1sig = mono_method_signature (m1);
4699 if (!cmsig || !m1sig) {
4700 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
4704 if (!strcmp(cm->name, m1->name) &&
4705 mono_metadata_signature_equal (cmsig, m1sig)) {
4707 if (mono_security_core_clr_enabled ())
4708 mono_security_core_clr_check_override (klass, cm, m1);
4710 slot = mono_method_get_vtable_slot (m1);
4714 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4715 char *body_name = mono_method_full_name (cm, TRUE);
4716 char *decl_name = mono_method_full_name (m1, TRUE);
4717 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));
4723 g_assert (cm->slot < max_vtsize);
4725 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4726 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4727 mono_method_full_name (m1, 1), m1,
4728 mono_method_full_name (cm, 1), cm));
4729 g_hash_table_insert (override_map, m1, cm);
4733 if (mono_class_has_failure (k))
4743 /*Non final newslot methods must be given a non-interface vtable slot*/
4744 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4748 cm->slot = cur_slot++;
4750 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4751 vtable [cm->slot] = cm;
4754 /* override non interface methods */
4755 for (i = 0; i < onum; i++) {
4756 MonoMethod *decl = overrides [i*2];
4757 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4758 g_assert (decl->slot != -1);
4759 vtable [decl->slot] = overrides [i*2 + 1];
4760 overrides [i * 2 + 1]->slot = decl->slot;
4762 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4763 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4764 mono_method_full_name (decl, 1), decl,
4765 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4766 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4768 if (mono_security_core_clr_enabled ())
4769 mono_security_core_clr_check_override (klass, vtable [decl->slot], decl);
4774 * If a method occupies more than one place in the vtable, and it is
4775 * overriden, then change the other occurances too.
4780 for (i = 0; i < max_vtsize; ++i)
4782 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4784 cm = (MonoMethod *)g_hash_table_lookup (override_map, vtable [i]);
4789 g_hash_table_destroy (override_map);
4790 override_map = NULL;
4793 g_slist_free (virt_methods);
4794 virt_methods = NULL;
4796 /* Ensure that all vtable slots are filled with concrete instance methods */
4797 if (!(klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4798 for (i = 0; i < cur_slot; ++i) {
4799 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4800 char *type_name = mono_type_get_full_name (klass);
4801 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4802 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));
4804 g_free (method_name);
4810 if (klass->generic_class) {
4811 MonoClass *gklass = klass->generic_class->container_class;
4813 mono_class_init (gklass);
4815 klass->vtable_size = MAX (gklass->vtable_size, cur_slot);
4817 /* Check that the vtable_size value computed in mono_class_init () is correct */
4818 if (klass->vtable_size)
4819 g_assert (cur_slot == klass->vtable_size);
4820 klass->vtable_size = cur_slot;
4823 /* Try to share the vtable with our parent. */
4824 if (klass->parent && (klass->parent->vtable_size == klass->vtable_size) && (memcmp (klass->parent->vtable, vtable, sizeof (gpointer) * klass->vtable_size) == 0)) {
4825 mono_memory_barrier ();
4826 klass->vtable = klass->parent->vtable;
4828 MonoMethod **tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * klass->vtable_size);
4829 memcpy (tmp, vtable, sizeof (gpointer) * klass->vtable_size);
4830 mono_memory_barrier ();
4831 klass->vtable = tmp;
4834 DEBUG_INTERFACE_VTABLE (print_vtable_full (klass, klass->vtable, klass->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4835 if (mono_print_vtable) {
4838 print_implemented_interfaces (klass);
4840 for (i = 0; i <= max_iid; i++)
4841 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
4844 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&klass->byval_arg),
4845 klass->vtable_size, icount);
4847 for (i = 0; i < cur_slot; ++i) {
4852 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4853 mono_method_full_name (cm, TRUE));
4859 printf ("Interfaces %s.%s (max_iid = %d)\n", klass->name_space,
4860 klass->name, max_iid);
4862 for (i = 0; i < klass->interface_count; i++) {
4863 ic = klass->interfaces [i];
4864 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4865 mono_class_interface_offset (klass, ic),
4866 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4869 for (k = klass->parent; k ; k = k->parent) {
4870 for (i = 0; i < k->interface_count; i++) {
4871 ic = k->interfaces [i];
4872 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4873 mono_class_interface_offset (klass, ic),
4874 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4880 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (klass));
4885 char *name = mono_type_get_full_name (klass);
4886 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("VTable setup of type %s failed", name));
4889 g_hash_table_destroy (override_map);
4891 g_slist_free (virt_methods);
4896 * mono_method_get_vtable_slot:
4898 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4899 * LOCKING: Acquires the loader lock.
4901 * FIXME Use proper MonoError machinery here.
4904 mono_method_get_vtable_slot (MonoMethod *method)
4906 if (method->slot == -1) {
4907 mono_class_setup_vtable (method->klass);
4908 if (mono_class_has_failure (method->klass))
4910 if (method->slot == -1) {
4914 if (!method->klass->generic_class) {
4915 g_assert (method->is_inflated);
4916 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4919 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4920 g_assert (method->klass->generic_class);
4921 gklass = method->klass->generic_class->container_class;
4922 mono_class_setup_methods (method->klass);
4923 g_assert (method->klass->methods);
4924 for (i = 0; i < method->klass->method.count; ++i) {
4925 if (method->klass->methods [i] == method)
4928 g_assert (i < method->klass->method.count);
4929 g_assert (gklass->methods);
4930 method->slot = gklass->methods [i]->slot;
4932 g_assert (method->slot != -1);
4934 return method->slot;
4938 * mono_method_get_vtable_index:
4941 * Returns the index into the runtime vtable to access the method or,
4942 * in the case of a virtual generic method, the virtual generic method
4943 * thunk. Returns -1 on failure.
4945 * FIXME Use proper MonoError machinery here.
4948 mono_method_get_vtable_index (MonoMethod *method)
4950 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4951 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4952 if (imethod->declaring->is_generic)
4953 return mono_method_get_vtable_slot (imethod->declaring);
4955 return mono_method_get_vtable_slot (method);
4958 static MonoMethod *default_ghc = NULL;
4959 static MonoMethod *default_finalize = NULL;
4960 static int finalize_slot = -1;
4961 static int ghc_slot = -1;
4964 initialize_object_slots (MonoClass *klass)
4969 if (klass == mono_defaults.object_class) {
4970 mono_class_setup_vtable (klass);
4971 for (i = 0; i < klass->vtable_size; ++i) {
4972 MonoMethod *cm = klass->vtable [i];
4974 if (!strcmp (cm->name, "GetHashCode"))
4976 else if (!strcmp (cm->name, "Finalize"))
4980 g_assert (ghc_slot > 0);
4981 default_ghc = klass->vtable [ghc_slot];
4983 g_assert (finalize_slot > 0);
4984 default_finalize = klass->vtable [finalize_slot];
4989 MonoMethod *array_method;
4991 } GenericArrayMethodInfo;
4993 static int generic_array_method_num = 0;
4994 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4997 generic_array_methods (MonoClass *klass)
4999 int i, count_generic = 0;
5000 GList *list = NULL, *tmp;
5001 if (generic_array_method_num)
5002 return generic_array_method_num;
5003 mono_class_setup_methods (klass->parent); /*This is setting up System.Array*/
5004 g_assert (!mono_class_has_failure (klass->parent)); /*So hitting this assert is a huge problem*/
5005 for (i = 0; i < klass->parent->method.count; i++) {
5006 MonoMethod *m = klass->parent->methods [i];
5007 if (!strncmp (m->name, "InternalArray__", 15)) {
5009 list = g_list_prepend (list, m);
5012 list = g_list_reverse (list);
5013 generic_array_method_info = (GenericArrayMethodInfo *)mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
5015 for (tmp = list; tmp; tmp = tmp->next) {
5016 const char *mname, *iname;
5018 MonoMethod *m = (MonoMethod *)tmp->data;
5019 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
5020 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
5022 generic_array_method_info [i].array_method = m;
5023 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
5024 iname = "System.Collections.Generic.ICollection`1.";
5025 mname = m->name + 27;
5026 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
5027 iname = "System.Collections.Generic.IEnumerable`1.";
5028 mname = m->name + 27;
5029 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
5030 iname = "System.Collections.Generic.IReadOnlyList`1.";
5031 mname = m->name + strlen (ireadonlylist_prefix);
5032 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
5033 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
5034 mname = m->name + strlen (ireadonlycollection_prefix);
5035 } else if (!strncmp (m->name, "InternalArray__", 15)) {
5036 iname = "System.Collections.Generic.IList`1.";
5037 mname = m->name + 15;
5039 g_assert_not_reached ();
5042 name = (gchar *)mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
5043 strcpy (name, iname);
5044 strcpy (name + strlen (iname), mname);
5045 generic_array_method_info [i].name = name;
5048 /*g_print ("array generic methods: %d\n", count_generic);*/
5050 generic_array_method_num = count_generic;
5052 return generic_array_method_num;
5056 setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos)
5058 MonoGenericContext tmp_context;
5061 tmp_context.class_inst = NULL;
5062 tmp_context.method_inst = iface->generic_class->context.class_inst;
5063 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
5065 for (i = 0; i < generic_array_method_num; i++) {
5067 MonoMethod *m = generic_array_method_info [i].array_method;
5068 MonoMethod *inflated;
5070 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
5071 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
5072 methods [pos++] = mono_marshal_get_generic_array_helper (klass, iface, generic_array_method_info [i].name, inflated);
5077 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
5079 int null_length = strlen ("(null)");
5080 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
5081 char *s = (char *)mono_image_alloc (image, len);
5084 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
5085 g_assert (result == len - 1);
5092 * @class: the class to initialize
5094 * Compute the instance_size, class_size and other infos that cannot be
5095 * computed at mono_class_get() time. Also compute vtable_size if possible.
5096 * Returns TRUE on success or FALSE if there was a problem in loading
5097 * the type (incorrect assemblies, missing assemblies, methods, etc).
5099 * LOCKING: Acquires the loader lock.
5102 mono_class_init (MonoClass *klass)
5105 MonoCachedClassInfo cached_info;
5106 gboolean has_cached_info;
5110 /* Double-checking locking pattern */
5111 if (klass->inited || mono_class_has_failure (klass))
5112 return !mono_class_has_failure (klass);
5114 /*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/
5116 /* We do everything inside the lock to prevent races */
5117 mono_loader_lock ();
5119 if (klass->inited || mono_class_has_failure (klass)) {
5120 mono_loader_unlock ();
5121 /* Somebody might have gotten in before us */
5122 return !mono_class_has_failure (klass);
5125 if (klass->init_pending) {
5126 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Recursive type definition detected"));
5130 klass->init_pending = 1;
5132 if (mono_verifier_is_enabled_for_class (klass) && !mono_verifier_verify_class (klass)) {
5133 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, concat_two_strings_with_zero (klass->image, klass->name, klass->image->assembly_name));
5138 if (klass->byval_arg.type == MONO_TYPE_ARRAY || klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5139 MonoClass *element_class = klass->element_class;
5140 if (!element_class->inited)
5141 mono_class_init (element_class);
5142 if (mono_class_has_failure (element_class)) {
5143 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5148 mono_stats.initialized_class_count++;
5150 if (klass->generic_class && !klass->generic_class->is_dynamic) {
5151 MonoClass *gklass = klass->generic_class->container_class;
5153 mono_stats.generic_class_count++;
5155 klass->method = gklass->method;
5156 klass->field = gklass->field;
5158 mono_class_init (gklass);
5159 // FIXME: Why is this needed ?
5160 if (!mono_class_has_failure (gklass))
5161 mono_class_setup_methods (gklass);
5162 if (mono_class_has_failure (gklass)) {
5163 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic Type Defintion failed to init"));
5167 if (MONO_CLASS_IS_INTERFACE (klass))
5168 klass->interface_id = mono_get_unique_iid (klass);
5171 if (klass->parent && !klass->parent->inited)
5172 mono_class_init (klass->parent);
5174 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
5176 if (klass->generic_class || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
5177 klass->nested_classes_inited = TRUE;
5180 * Computes the size used by the fields, and their locations
5182 if (has_cached_info) {
5183 klass->instance_size = cached_info.instance_size;
5184 klass->sizes.class_size = cached_info.class_size;
5185 klass->packing_size = cached_info.packing_size;
5186 klass->min_align = cached_info.min_align;
5187 klass->blittable = cached_info.blittable;
5188 klass->has_references = cached_info.has_references;
5189 klass->has_static_refs = cached_info.has_static_refs;
5190 klass->no_special_static_fields = cached_info.no_special_static_fields;
5193 if (!klass->size_inited){
5194 mono_class_setup_fields (klass);
5195 if (mono_class_has_failure (klass))
5199 /* Initialize arrays */
5201 klass->method.count = 3 + (klass->rank > 1? 2: 1);
5203 if (klass->interface_count) {
5204 int count_generic = generic_array_methods (klass);
5205 klass->method.count += klass->interface_count * count_generic;
5209 mono_class_setup_supertypes (klass);
5212 initialize_object_slots (klass);
5215 * Initialize the rest of the data without creating a generic vtable if possible.
5216 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5217 * also avoid computing a generic vtable.
5219 if (has_cached_info) {
5221 klass->vtable_size = cached_info.vtable_size;
5222 klass->has_finalize = cached_info.has_finalize;
5223 klass->has_finalize_inited = TRUE;
5224 klass->ghcimpl = cached_info.ghcimpl;
5225 klass->has_cctor = cached_info.has_cctor;
5226 } else if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5227 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5228 * The first slot if for array with.
5230 static int szarray_vtable_size[2] = { 0 };
5232 int slot = MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg) ? 0 : 1;
5235 if (!szarray_vtable_size [slot]) {
5236 mono_class_setup_vtable (klass);
5237 szarray_vtable_size [slot] = klass->vtable_size;
5239 klass->vtable_size = szarray_vtable_size[slot];
5241 } else if (klass->generic_class && !MONO_CLASS_IS_INTERFACE (klass)) {
5242 MonoClass *gklass = klass->generic_class->container_class;
5244 /* Generic instance case */
5245 klass->ghcimpl = gklass->ghcimpl;
5246 klass->has_cctor = gklass->has_cctor;
5248 mono_class_setup_vtable (gklass);
5249 if (mono_class_has_failure (gklass)) {
5250 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5254 klass->vtable_size = gklass->vtable_size;
5258 /* ghcimpl is not currently used
5260 if (klass->parent) {
5261 MonoMethod *cmethod = klass->vtable [ghc_slot];
5262 if (cmethod->is_inflated)
5263 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5264 if (cmethod == default_ghc) {
5270 /* C# doesn't allow interfaces to have cctors */
5271 if (!MONO_CLASS_IS_INTERFACE (klass) || klass->image != mono_defaults.corlib) {
5272 MonoMethod *cmethod = NULL;
5274 if (klass->type_token && !image_is_dynamic(klass->image)) {
5275 cmethod = find_method_in_metadata (klass, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5276 /* The find_method function ignores the 'flags' argument */
5277 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5278 klass->has_cctor = 1;
5280 mono_class_setup_methods (klass);
5281 if (mono_class_has_failure (klass))
5284 for (i = 0; i < klass->method.count; ++i) {
5285 MonoMethod *method = klass->methods [i];
5286 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5287 (strcmp (".cctor", method->name) == 0)) {
5288 klass->has_cctor = 1;
5296 if (klass->parent) {
5297 int first_iface_slot;
5298 /* This will compute klass->parent->vtable_size for some classes */
5299 mono_class_init (klass->parent);
5300 if (mono_class_has_failure (klass->parent)) {
5301 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5304 if (!klass->parent->vtable_size) {
5305 /* FIXME: Get rid of this somehow */
5306 mono_class_setup_vtable (klass->parent);
5307 if (mono_class_has_failure (klass->parent)) {
5308 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5312 first_iface_slot = klass->parent->vtable_size;
5313 if (mono_class_need_stelemref_method (klass))
5315 setup_interface_offsets (klass, first_iface_slot, TRUE);
5317 setup_interface_offsets (klass, 0, TRUE);
5320 if (mono_security_core_clr_enabled ())
5321 mono_security_core_clr_check_inheritance (klass);
5323 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass))
5324 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Invalid generic instantiation"));
5329 /* Because of the double-checking locking pattern */
5330 mono_memory_barrier ();
5332 klass->init_pending = 0;
5334 mono_loader_unlock ();
5336 return !mono_class_has_failure (klass);
5340 * mono_class_has_finalizer:
5342 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5346 mono_class_has_finalizer (MonoClass *klass)
5348 gboolean has_finalize = FALSE;
5350 if (klass->has_finalize_inited)
5351 return klass->has_finalize;
5353 /* Interfaces and valuetypes are not supposed to have finalizers */
5354 if (!(MONO_CLASS_IS_INTERFACE (klass) || klass->valuetype)) {
5355 MonoMethod *cmethod = NULL;
5357 if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5358 } else if (klass->generic_class) {
5359 MonoClass *gklass = klass->generic_class->container_class;
5361 has_finalize = mono_class_has_finalizer (gklass);
5362 } else if (klass->parent && klass->parent->has_finalize) {
5363 has_finalize = TRUE;
5365 if (klass->parent) {
5367 * Can't search in metadata for a method named Finalize, because that
5368 * ignores overrides.
5370 mono_class_setup_vtable (klass);
5371 if (mono_class_has_failure (klass))
5374 cmethod = klass->vtable [finalize_slot];
5378 g_assert (klass->vtable_size > finalize_slot);
5380 if (klass->parent) {
5381 if (cmethod->is_inflated)
5382 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5383 if (cmethod != default_finalize)
5384 has_finalize = TRUE;
5390 mono_image_lock (klass->image);
5392 if (!klass->has_finalize_inited) {
5393 klass->has_finalize = has_finalize ? 1 : 0;
5395 mono_memory_barrier ();
5396 klass->has_finalize_inited = TRUE;
5399 mono_image_unlock (klass->image);
5401 return klass->has_finalize;
5405 mono_is_corlib_image (MonoImage *image)
5407 /* FIXME: allow the dynamic case for our compilers and with full trust */
5408 if (image_is_dynamic (image))
5409 return image->assembly && !strcmp (image->assembly->aname.name, "mscorlib");
5411 return image == mono_defaults.corlib;
5415 * LOCKING: this assumes the loader lock is held
5418 mono_class_setup_mono_type (MonoClass *klass)
5420 const char *name = klass->name;
5421 const char *nspace = klass->name_space;
5422 gboolean is_corlib = mono_is_corlib_image (klass->image);
5424 klass->this_arg.byref = 1;
5425 klass->this_arg.data.klass = klass;
5426 klass->this_arg.type = MONO_TYPE_CLASS;
5427 klass->byval_arg.data.klass = klass;
5428 klass->byval_arg.type = MONO_TYPE_CLASS;
5430 if (is_corlib && !strcmp (nspace, "System")) {
5431 if (!strcmp (name, "ValueType")) {
5433 * do not set the valuetype bit for System.ValueType.
5434 * klass->valuetype = 1;
5436 klass->blittable = TRUE;
5437 } else if (!strcmp (name, "Enum")) {
5439 * do not set the valuetype bit for System.Enum.
5440 * klass->valuetype = 1;
5442 klass->valuetype = 0;
5443 klass->enumtype = 0;
5444 } else if (!strcmp (name, "Object")) {
5445 klass->byval_arg.type = MONO_TYPE_OBJECT;
5446 klass->this_arg.type = MONO_TYPE_OBJECT;
5447 } else if (!strcmp (name, "String")) {
5448 klass->byval_arg.type = MONO_TYPE_STRING;
5449 klass->this_arg.type = MONO_TYPE_STRING;
5450 } else if (!strcmp (name, "TypedReference")) {
5451 klass->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5452 klass->this_arg.type = MONO_TYPE_TYPEDBYREF;
5456 if (klass->valuetype) {
5457 int t = MONO_TYPE_VALUETYPE;
5459 if (is_corlib && !strcmp (nspace, "System")) {
5462 if (!strcmp (name, "Boolean")) {
5463 t = MONO_TYPE_BOOLEAN;
5464 } else if (!strcmp(name, "Byte")) {
5466 klass->blittable = TRUE;
5470 if (!strcmp (name, "Char")) {
5475 if (!strcmp (name, "Double")) {
5477 klass->blittable = TRUE;
5481 if (!strcmp (name, "Int32")) {
5483 klass->blittable = TRUE;
5484 } else if (!strcmp(name, "Int16")) {
5486 klass->blittable = TRUE;
5487 } else if (!strcmp(name, "Int64")) {
5489 klass->blittable = TRUE;
5490 } else if (!strcmp(name, "IntPtr")) {
5492 klass->blittable = TRUE;
5496 if (!strcmp (name, "Single")) {
5498 klass->blittable = TRUE;
5499 } else if (!strcmp(name, "SByte")) {
5501 klass->blittable = TRUE;
5505 if (!strcmp (name, "UInt32")) {
5507 klass->blittable = TRUE;
5508 } else if (!strcmp(name, "UInt16")) {
5510 klass->blittable = TRUE;
5511 } else if (!strcmp(name, "UInt64")) {
5513 klass->blittable = TRUE;
5514 } else if (!strcmp(name, "UIntPtr")) {
5516 klass->blittable = TRUE;
5520 if (!strcmp (name, "TypedReference")) {
5521 t = MONO_TYPE_TYPEDBYREF;
5522 klass->blittable = TRUE;
5526 if (!strcmp (name, "Void")) {
5534 klass->byval_arg.type = (MonoTypeEnum)t;
5535 klass->this_arg.type = (MonoTypeEnum)t;
5538 if (MONO_CLASS_IS_INTERFACE (klass))
5539 klass->interface_id = mono_get_unique_iid (klass);
5545 * COM initialization is delayed until needed.
5546 * However when a [ComImport] attribute is present on a type it will trigger
5547 * the initialization. This is not a problem unless the BCL being executed
5548 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5551 init_com_from_comimport (MonoClass *klass)
5553 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5554 if (mono_security_core_clr_enabled ()) {
5555 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5556 if (!mono_security_core_clr_determine_platform_image (klass->image)) {
5557 /* but it can not be made available for application (i.e. user code) since all COM calls
5558 * are considered native calls. In this case we fail with a TypeLoadException (just like
5559 * Silverlight 2 does */
5560 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5565 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5567 #endif /*DISABLE_COM*/
5570 * LOCKING: this assumes the loader lock is held
5573 mono_class_setup_parent (MonoClass *klass, MonoClass *parent)
5575 gboolean system_namespace;
5576 gboolean is_corlib = mono_is_corlib_image (klass->image);
5578 system_namespace = !strcmp (klass->name_space, "System") && is_corlib;
5580 /* if root of the hierarchy */
5581 if (system_namespace && !strcmp (klass->name, "Object")) {
5582 klass->parent = NULL;
5583 klass->instance_size = sizeof (MonoObject);
5586 if (!strcmp (klass->name, "<Module>")) {
5587 klass->parent = NULL;
5588 klass->instance_size = 0;
5592 if (!MONO_CLASS_IS_INTERFACE (klass)) {
5593 /* Imported COM Objects always derive from __ComObject. */
5595 if (MONO_CLASS_IS_IMPORT (klass)) {
5596 init_com_from_comimport (klass);
5597 if (parent == mono_defaults.object_class)
5598 parent = mono_class_get_com_object_class ();
5602 /* set the parent to something useful and safe, but mark the type as broken */
5603 parent = mono_defaults.object_class;
5604 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5607 klass->parent = parent;
5609 if (parent->generic_class && !parent->name) {
5611 * If the parent is a generic instance, we may get
5612 * called before it is fully initialized, especially
5613 * before it has its name.
5618 #ifndef DISABLE_REMOTING
5619 klass->marshalbyref = parent->marshalbyref;
5620 klass->contextbound = parent->contextbound;
5623 klass->delegate = parent->delegate;
5625 if (MONO_CLASS_IS_IMPORT (klass) || mono_class_is_com_object (parent))
5626 mono_class_set_is_com_object (klass);
5628 if (system_namespace) {
5629 #ifndef DISABLE_REMOTING
5630 if (klass->name [0] == 'M' && !strcmp (klass->name, "MarshalByRefObject"))
5631 klass->marshalbyref = 1;
5633 if (klass->name [0] == 'C' && !strcmp (klass->name, "ContextBoundObject"))
5634 klass->contextbound = 1;
5636 if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate"))
5637 klass->delegate = 1;
5640 if (klass->parent->enumtype || (mono_is_corlib_image (klass->parent->image) && (strcmp (klass->parent->name, "ValueType") == 0) &&
5641 (strcmp (klass->parent->name_space, "System") == 0)))
5642 klass->valuetype = 1;
5643 if (mono_is_corlib_image (klass->parent->image) && ((strcmp (klass->parent->name, "Enum") == 0) && (strcmp (klass->parent->name_space, "System") == 0))) {
5644 klass->valuetype = klass->enumtype = 1;
5646 /*klass->enumtype = klass->parent->enumtype; */
5648 /* initialize com types if COM interfaces are present */
5650 if (MONO_CLASS_IS_IMPORT (klass))
5651 init_com_from_comimport (klass);
5653 klass->parent = NULL;
5659 * mono_class_setup_supertypes:
5662 * Build the data structure needed to make fast type checks work.
5663 * This currently sets two fields in @class:
5664 * - idepth: distance between @class and System.Object in the type
5666 * - supertypes: array of classes: each element has a class in the hierarchy
5667 * starting from @class up to System.Object
5669 * LOCKING: This function is atomic, in case of contention we waste memory.
5672 mono_class_setup_supertypes (MonoClass *klass)
5675 MonoClass **supertypes;
5677 mono_atomic_load_acquire (supertypes, MonoClass **, &klass->supertypes);
5681 if (klass->parent && !klass->parent->supertypes)
5682 mono_class_setup_supertypes (klass->parent);
5684 klass->idepth = klass->parent->idepth + 1;
5688 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, klass->idepth);
5689 supertypes = (MonoClass **)mono_class_alloc0 (klass, sizeof (MonoClass *) * ms);
5691 if (klass->parent) {
5692 CHECKED_METADATA_WRITE_PTR ( supertypes [klass->idepth - 1] , klass );
5695 for (supertype_idx = 0; supertype_idx < klass->parent->idepth; supertype_idx++)
5696 CHECKED_METADATA_WRITE_PTR ( supertypes [supertype_idx] , klass->parent->supertypes [supertype_idx] );
5698 CHECKED_METADATA_WRITE_PTR ( supertypes [0] , klass );
5701 CHECKED_METADATA_WRITE_PTR_ATOMIC ( klass->supertypes , supertypes );
5705 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5707 MonoClass *gtd = (MonoClass*)user_data;
5708 /* Only try to fix generic instances of @gtd */
5709 if (gclass->generic_class->container_class != gtd)
5712 /* Check if the generic instance has no parent. */
5713 if (gtd->parent && !gclass->parent)
5714 mono_generic_class_setup_parent (gclass, gtd);
5720 mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char *msg)
5722 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (msg));
5723 mono_error_set_type_load_class (error, klass, msg);
5727 * mono_class_create_from_typedef:
5728 * @image: image where the token is valid
5729 * @type_token: typedef token
5730 * @error: used to return any error found while creating the type
5732 * Create the MonoClass* representing the specified type token.
5733 * @type_token must be a TypeDef token.
5735 * FIXME: don't return NULL on failure, just the the caller figure it out.
5738 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5740 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5741 MonoClass *klass, *parent = NULL;
5742 guint32 cols [MONO_TYPEDEF_SIZE];
5743 guint32 cols_next [MONO_TYPEDEF_SIZE];
5744 guint tidx = mono_metadata_token_index (type_token);
5745 MonoGenericContext *context = NULL;
5746 const char *name, *nspace;
5748 MonoClass **interfaces;
5749 guint32 field_last, method_last;
5750 guint32 nesting_tokeen;
5752 mono_error_init (error);
5754 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5755 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5759 mono_loader_lock ();
5761 if ((klass = (MonoClass *)mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5762 mono_loader_unlock ();
5766 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5768 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5769 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5771 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
5774 klass->name_space = nspace;
5776 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5778 klass->image = image;
5779 klass->type_token = type_token;
5780 klass->flags = cols [MONO_TYPEDEF_FLAGS];
5782 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
5784 classes_size += sizeof (MonoClass);
5787 * Check whether we're a generic type definition.
5789 klass->generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
5790 if (klass->generic_container) {
5791 klass->is_generic = 1;
5792 klass->generic_container->owner.klass = klass;
5793 klass->generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
5794 context = &klass->generic_container->context;
5797 if (klass->generic_container)
5798 enable_gclass_recording ();
5800 if (cols [MONO_TYPEDEF_EXTENDS]) {
5802 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5804 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5805 /*WARNING: this must satisfy mono_metadata_type_hash*/
5806 klass->this_arg.byref = 1;
5807 klass->this_arg.data.klass = klass;
5808 klass->this_arg.type = MONO_TYPE_CLASS;
5809 klass->byval_arg.data.klass = klass;
5810 klass->byval_arg.type = MONO_TYPE_CLASS;
5812 parent = mono_class_get_checked (image, parent_token, error);
5813 if (parent && context) /* Always inflate */
5814 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5816 if (parent == NULL) {
5817 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5818 goto parent_failure;
5821 for (tmp = parent; tmp; tmp = tmp->parent) {
5823 mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
5824 goto parent_failure;
5826 if (klass->generic_container && tmp->generic_class && tmp->generic_class->container_class == klass) {
5827 mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
5828 goto parent_failure;
5833 mono_class_setup_parent (klass, parent);
5835 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5836 mono_class_setup_mono_type (klass);
5838 if (klass->generic_container)
5839 disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
5842 * This might access klass->byval_arg for recursion generated by generic constraints,
5843 * so it has to come after setup_mono_type ().
5845 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5846 klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5847 if (!mono_error_ok (error)) {
5848 /*FIXME implement a mono_class_set_failure_from_mono_error */
5849 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5850 mono_loader_unlock ();
5851 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5856 if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5860 if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5864 klass->cast_class = klass->element_class = klass;
5866 if (!klass->enumtype) {
5867 if (!mono_metadata_interfaces_from_typedef_full (
5868 image, type_token, &interfaces, &icount, FALSE, context, error)){
5870 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5871 mono_loader_unlock ();
5872 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5876 klass->interfaces = interfaces;
5877 klass->interface_count = icount;
5878 klass->interfaces_inited = 1;
5881 /*g_print ("Load class %s\n", name);*/
5884 * Compute the field and method lists
5886 klass->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5887 klass->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5889 if (tt->rows > tidx){
5890 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5891 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5892 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5894 field_last = image->tables [MONO_TABLE_FIELD].rows;
5895 method_last = image->tables [MONO_TABLE_METHOD].rows;
5898 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5899 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5900 klass->field.count = field_last - klass->field.first;
5902 klass->field.count = 0;
5904 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5905 klass->method.count = method_last - klass->method.first;
5907 klass->method.count = 0;
5909 /* reserve space to store vector pointer in arrays */
5910 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5911 klass->instance_size += 2 * sizeof (gpointer);
5912 g_assert (klass->field.count == 0);
5915 if (klass->enumtype) {
5916 MonoType *enum_basetype = mono_class_find_enum_basetype (klass, error);
5917 if (!enum_basetype) {
5918 /*set it to a default value as the whole runtime can't handle this to be null*/
5919 klass->cast_class = klass->element_class = mono_defaults.int32_class;
5920 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5921 mono_loader_unlock ();
5922 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5925 klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
5929 * If we're a generic type definition, load the constraints.
5930 * We must do this after the class has been constructed to make certain recursive scenarios
5933 if (klass->generic_container && !mono_metadata_load_generic_param_constraints_checked (image, type_token, klass->generic_container, error)) {
5934 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)));
5935 mono_loader_unlock ();
5936 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5940 if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5941 if (!strncmp (name, "Vector", 6))
5942 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");
5945 mono_loader_unlock ();
5947 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5952 mono_class_setup_mono_type (klass);
5953 mono_loader_unlock ();
5954 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5958 /** Is klass a Nullable<T> ginst? */
5960 mono_class_is_nullable (MonoClass *klass)
5962 return klass->generic_class != NULL &&
5963 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5967 /** if klass is T? return T */
5969 mono_class_get_nullable_param (MonoClass *klass)
5971 g_assert (mono_class_is_nullable (klass));
5972 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5976 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5980 MonoGenericClass *gclass = klass->generic_class;
5982 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5983 if (!mono_error_ok (&error)) {
5984 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5985 klass->parent = mono_defaults.object_class;
5986 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5987 mono_error_cleanup (&error);
5991 mono_class_setup_parent (klass, klass->parent);
5993 if (klass->enumtype) {
5994 klass->cast_class = gtd->cast_class;
5995 klass->element_class = gtd->element_class;
6001 * Create the `MonoClass' for an instantiation of a generic type.
6002 * We only do this if we actually need it.
6005 mono_generic_class_get_class (MonoGenericClass *gclass)
6007 MonoClass *klass, *gklass;
6009 if (gclass->cached_class)
6010 return gclass->cached_class;
6012 mono_loader_lock ();
6013 if (gclass->cached_class) {
6014 mono_loader_unlock ();
6015 return gclass->cached_class;
6018 klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
6020 gklass = gclass->container_class;
6022 if (record_gclass_instantiation > 0)
6023 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
6025 if (gklass->nested_in) {
6026 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
6027 klass->nested_in = gklass->nested_in;
6030 klass->name = gklass->name;
6031 klass->name_space = gklass->name_space;
6033 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6035 klass->image = gklass->image;
6036 klass->flags = gklass->flags;
6037 klass->type_token = gklass->type_token;
6038 klass->field.count = gklass->field.count;
6040 klass->is_inflated = 1;
6041 klass->generic_class = gclass;
6043 klass->byval_arg.type = MONO_TYPE_GENERICINST;
6044 klass->this_arg.type = klass->byval_arg.type;
6045 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
6046 klass->this_arg.byref = TRUE;
6047 klass->enumtype = gklass->enumtype;
6048 klass->valuetype = gklass->valuetype;
6050 klass->cast_class = klass->element_class = klass;
6052 if (mono_class_is_nullable (klass))
6053 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
6056 * We're not interested in the nested classes of a generic instance.
6057 * We use the generic type definition to look for nested classes.
6060 mono_generic_class_setup_parent (klass, gklass);
6062 if (gclass->is_dynamic) {
6064 * 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.
6065 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
6066 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
6068 if (!gklass->wastypebuilder)
6071 mono_class_setup_supertypes (klass);
6073 if (klass->enumtype) {
6075 * For enums, gklass->fields might not been set, but instance_size etc. is
6076 * already set in mono_reflection_create_internal_class (). For non-enums,
6077 * these will be computed normally in mono_class_layout_fields ().
6079 klass->instance_size = gklass->instance_size;
6080 klass->sizes.class_size = gklass->sizes.class_size;
6081 mono_memory_barrier ();
6082 klass->size_inited = 1;
6086 mono_memory_barrier ();
6087 gclass->cached_class = klass;
6089 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6091 inflated_classes ++;
6092 inflated_classes_size += sizeof (MonoClass);
6094 mono_loader_unlock ();
6100 get_image_for_container (MonoGenericContainer *container)
6103 if (container->is_anonymous) {
6104 result = container->owner.image;
6107 if (container->is_method) {
6108 MonoMethod *method = container->owner.method;
6109 g_assert_checked (method);
6110 klass = method->klass;
6112 klass = container->owner.klass;
6114 g_assert_checked (klass);
6115 result = klass->image;
6122 get_image_for_generic_param (MonoGenericParam *param)
6124 MonoGenericContainer *container = mono_generic_param_owner (param);
6125 g_assert_checked (container);
6126 return get_image_for_container (container);
6129 // Make a string in the designated image consisting of a single integer.
6130 #define INT_STRING_SIZE 16
6132 make_generic_name_string (MonoImage *image, int num)
6134 char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
6135 g_snprintf (name, INT_STRING_SIZE, "%d", num);
6139 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
6140 // pinfo is derived from param by the caller for us.
6142 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
6144 MonoClass *klass, **ptr;
6146 MonoGenericContainer *container = mono_generic_param_owner (param);
6147 g_assert_checked (container);
6149 MonoImage *image = get_image_for_container (container);
6150 gboolean is_mvar = container->is_method;
6151 gboolean is_anonymous = container->is_anonymous;
6153 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6154 classes_size += sizeof (MonoClass);
6157 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
6159 int n = mono_generic_param_num (param);
6160 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
6164 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , "" );
6165 } else if (is_mvar) {
6166 MonoMethod *omethod = container->owner.method;
6167 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
6169 MonoClass *oklass = container->owner.klass;
6170 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
6173 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6175 // Count non-NULL items in pinfo->constraints
6178 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6182 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6183 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
6185 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
6186 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
6188 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
6191 if (count - pos > 0) {
6192 klass->interface_count = count - pos;
6193 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
6194 klass->interfaces_inited = TRUE;
6195 for (i = pos; i < count; i++)
6196 CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
6199 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
6201 klass->inited = TRUE;
6202 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class , klass );
6203 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
6204 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
6206 klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6207 klass->this_arg.type = klass->byval_arg.type;
6208 CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param , param );
6209 CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
6210 klass->this_arg.byref = TRUE;
6212 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6213 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6215 /*Init these fields to sane values*/
6216 klass->min_align = 1;
6218 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6219 * constrained to, the JIT depends on this.
6221 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6222 mono_memory_barrier ();
6223 klass->size_inited = 1;
6224 klass->setup_fields_called = 1;
6226 mono_class_setup_supertypes (klass);
6228 if (count - pos > 0) {
6229 mono_class_setup_vtable (klass->parent);
6230 if (mono_class_has_failure (klass->parent))
6231 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
6233 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6239 #define FAST_CACHE_SIZE 16
6242 * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6243 * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6244 * we cache the MonoClasses.
6245 * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6246 * LOCKING: Takes the image lock depending on @take_lock.
6249 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6251 int n = mono_generic_param_num (param);
6252 MonoImage *image = get_image_for_generic_param (param);
6253 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6254 MonoClass *klass = NULL;
6259 // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6260 // For high numbers or constraints we have to use pointer hashes.
6261 if (param->gshared_constraint) {
6262 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6265 mono_image_lock (image);
6266 klass = (MonoClass *)g_hash_table_lookup (ht, param);
6268 mono_image_unlock (image);
6273 if (n < FAST_CACHE_SIZE) {
6275 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6277 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6279 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6282 mono_image_lock (image);
6283 klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6285 mono_image_unlock (image);
6292 * LOCKING: Image lock (param->image) must be held
6295 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6297 int n = mono_generic_param_num (param);
6298 MonoImage *image = get_image_for_generic_param (param);
6299 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6303 if (param->gshared_constraint) {
6304 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6306 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6307 mono_memory_barrier ();
6309 image->mvar_cache_constrained = ht;
6311 image->var_cache_constrained = ht;
6313 g_hash_table_insert (ht, param, klass);
6314 } else if (n < FAST_CACHE_SIZE) {
6316 /* Requires locking to avoid droping an already published class */
6317 if (!image->mvar_cache_fast)
6318 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6319 image->mvar_cache_fast [n] = klass;
6321 if (!image->var_cache_fast)
6322 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6323 image->var_cache_fast [n] = klass;
6326 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6328 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6330 ht = g_hash_table_new (NULL, NULL);
6331 mono_memory_barrier ();
6333 image->mvar_cache_slow = ht;
6335 image->var_cache_slow = ht;
6338 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6343 * LOCKING: Acquires the image lock (@image).
6346 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6348 MonoImage *image = get_image_for_generic_param (param);
6349 MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6350 MonoClass *klass, *klass2;
6352 // If a klass already exists for this object and is cached, return it.
6353 if (pinfo) // Non-anonymous
6354 klass = pinfo->pklass;
6356 klass = get_anon_gparam_class (param, TRUE);
6361 // Create a new klass
6362 klass = make_generic_param_class (param, pinfo);
6364 // Now we need to cache the klass we created.
6365 // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6366 // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6367 // and allow our newly-created klass object to just leak.
6368 mono_memory_barrier ();
6370 mono_image_lock (image);
6372 // Here "klass2" refers to the klass potentially created by the other thread.
6373 if (pinfo) // Repeat check from above
6374 klass2 = pinfo->pklass;
6376 klass2 = get_anon_gparam_class (param, FALSE);
6383 pinfo->pklass = klass;
6385 set_anon_gparam_class (param, klass);
6387 mono_image_unlock (image);
6389 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6391 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED); // Alert profiler about botched class create
6393 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6399 * mono_class_from_generic_parameter:
6400 * @param: Parameter to find/construct a class for.
6401 * @arg2: Is ignored.
6402 * @arg3: Is ignored.
6405 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6407 return mono_class_from_generic_parameter_internal (param);
6412 mono_ptr_class_get (MonoType *type)
6415 MonoClass *el_class;
6419 el_class = mono_class_from_mono_type (type);
6420 image = el_class->image;
6422 mono_image_lock (image);
6423 if (image->ptr_cache) {
6424 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6425 mono_image_unlock (image);
6429 mono_image_unlock (image);
6431 result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6433 classes_size += sizeof (MonoClass);
6435 result->parent = NULL; /* no parent for PTR types */
6436 result->name_space = el_class->name_space;
6437 name = g_strdup_printf ("%s*", el_class->name);
6438 result->name = mono_image_strdup (image, name);
6441 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6443 result->image = el_class->image;
6444 result->inited = TRUE;
6445 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6446 /* Can pointers get boxed? */
6447 result->instance_size = sizeof (gpointer);
6448 result->cast_class = result->element_class = el_class;
6449 result->blittable = TRUE;
6451 result->byval_arg.type = MONO_TYPE_PTR;
6452 result->this_arg.type = result->byval_arg.type;
6453 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6454 result->this_arg.byref = TRUE;
6456 mono_class_setup_supertypes (result);
6458 mono_image_lock (image);
6459 if (image->ptr_cache) {
6461 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6462 mono_image_unlock (image);
6463 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6467 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6469 g_hash_table_insert (image->ptr_cache, el_class, result);
6470 mono_image_unlock (image);
6472 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6478 mono_fnptr_class_get (MonoMethodSignature *sig)
6481 static GHashTable *ptr_hash = NULL;
6483 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6485 mono_loader_lock ();
6488 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6490 if ((result = (MonoClass *)g_hash_table_lookup (ptr_hash, sig))) {
6491 mono_loader_unlock ();
6494 result = g_new0 (MonoClass, 1);
6496 result->parent = NULL; /* no parent for PTR types */
6497 result->name_space = "System";
6498 result->name = "MonoFNPtrFakeClass";
6500 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6502 result->image = mono_defaults.corlib; /* need to fix... */
6503 result->inited = TRUE;
6504 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6505 /* Can pointers get boxed? */
6506 result->instance_size = sizeof (gpointer);
6507 result->cast_class = result->element_class = result;
6508 result->blittable = TRUE;
6510 result->byval_arg.type = MONO_TYPE_FNPTR;
6511 result->this_arg.type = result->byval_arg.type;
6512 result->this_arg.data.method = result->byval_arg.data.method = sig;
6513 result->this_arg.byref = TRUE;
6514 result->blittable = TRUE;
6516 mono_class_setup_supertypes (result);
6518 g_hash_table_insert (ptr_hash, sig, result);
6520 mono_loader_unlock ();
6522 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6528 * mono_class_from_mono_type:
6529 * @type: describes the type to return
6531 * This returns a MonoClass for the specified MonoType, the value is never NULL.
6534 mono_class_from_mono_type (MonoType *type)
6536 switch (type->type) {
6537 case MONO_TYPE_OBJECT:
6538 return type->data.klass? type->data.klass: mono_defaults.object_class;
6539 case MONO_TYPE_VOID:
6540 return type->data.klass? type->data.klass: mono_defaults.void_class;
6541 case MONO_TYPE_BOOLEAN:
6542 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6543 case MONO_TYPE_CHAR:
6544 return type->data.klass? type->data.klass: mono_defaults.char_class;
6546 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6548 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6550 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6552 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6554 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6556 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6558 return type->data.klass? type->data.klass: mono_defaults.int_class;
6560 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6562 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6564 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6566 return type->data.klass? type->data.klass: mono_defaults.single_class;
6568 return type->data.klass? type->data.klass: mono_defaults.double_class;
6569 case MONO_TYPE_STRING:
6570 return type->data.klass? type->data.klass: mono_defaults.string_class;
6571 case MONO_TYPE_TYPEDBYREF:
6572 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6573 case MONO_TYPE_ARRAY:
6574 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6576 return mono_ptr_class_get (type->data.type);
6577 case MONO_TYPE_FNPTR:
6578 return mono_fnptr_class_get (type->data.method);
6579 case MONO_TYPE_SZARRAY:
6580 return mono_array_class_get (type->data.klass, 1);
6581 case MONO_TYPE_CLASS:
6582 case MONO_TYPE_VALUETYPE:
6583 return type->data.klass;
6584 case MONO_TYPE_GENERICINST:
6585 return mono_generic_class_get_class (type->data.generic_class);
6586 case MONO_TYPE_MVAR:
6588 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6590 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6591 g_assert_not_reached ();
6594 // Yes, this returns NULL, even if it is documented as not doing so, but there
6595 // is no way for the code to make it this far, due to the assert above.
6600 * mono_type_retrieve_from_typespec
6601 * @image: context where the image is created
6602 * @type_spec: typespec token
6603 * @context: the generic context used to evaluate generic instantiations in
6606 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6608 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6610 *did_inflate = FALSE;
6615 if (context && (context->class_inst || context->method_inst)) {
6616 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6618 if (!mono_error_ok (error)) {
6624 *did_inflate = TRUE;
6631 * mono_class_create_from_typespec
6632 * @image: context where the image is created
6633 * @type_spec: typespec token
6634 * @context: the generic context used to evaluate generic instantiations in
6637 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6640 gboolean inflated = FALSE;
6641 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6642 return_val_if_nok (error, NULL);
6643 ret = mono_class_from_mono_type (t);
6645 mono_metadata_free_type (t);
6650 * mono_bounded_array_class_get:
6651 * @element_class: element class
6652 * @rank: the dimension of the array class
6653 * @bounded: whenever the array has non-zero bounds
6655 * Returns: A class object describing the array with element type @element_type and
6659 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6663 MonoClass *parent = NULL;
6664 GSList *list, *rootlist = NULL;
6667 gboolean corlib_type = FALSE;
6669 g_assert (rank <= 255);
6672 /* bounded only matters for one-dimensional arrays */
6675 image = eclass->image;
6677 if (rank == 1 && !bounded) {
6679 * This case is very frequent not just during compilation because of calls
6680 * from mono_class_from_mono_type (), mono_array_new (),
6681 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6683 mono_os_mutex_lock (&image->szarray_cache_lock);
6684 if (!image->szarray_cache)
6685 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6686 klass = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6687 mono_os_mutex_unlock (&image->szarray_cache_lock);
6691 mono_loader_lock ();
6693 mono_loader_lock ();
6695 if (!image->array_cache)
6696 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6698 if ((rootlist = list = (GSList *)g_hash_table_lookup (image->array_cache, eclass))) {
6699 for (; list; list = list->next) {
6700 klass = (MonoClass *)list->data;
6701 if ((klass->rank == rank) && (klass->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6702 mono_loader_unlock ();
6709 /* for the building corlib use System.Array from it */
6710 if (image->assembly && assembly_is_dynamic (image->assembly) && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6711 parent = mono_class_load_from_name (image, "System", "Array");
6714 parent = mono_defaults.array_class;
6715 if (!parent->inited)
6716 mono_class_init (parent);
6719 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6721 klass->image = image;
6722 klass->name_space = eclass->name_space;
6723 nsize = strlen (eclass->name);
6724 name = (char *)g_malloc (nsize + 2 + rank + 1);
6725 memcpy (name, eclass->name, nsize);
6728 memset (name + nsize + 1, ',', rank - 1);
6730 name [nsize + rank] = '*';
6731 name [nsize + rank + bounded] = ']';
6732 name [nsize + rank + bounded + 1] = 0;
6733 klass->name = mono_image_strdup (image, name);
6736 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6738 classes_size += sizeof (MonoClass);
6740 klass->type_token = 0;
6741 /* all arrays are marked serializable and sealed, bug #42779 */
6742 klass->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6743 klass->parent = parent;
6744 klass->instance_size = mono_class_instance_size (klass->parent);
6746 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6747 /*Arrays of those two types are invalid.*/
6748 mono_class_set_failure (klass, MONO_EXCEPTION_INVALID_PROGRAM, NULL);
6749 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6750 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6751 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6752 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6754 /* element_size -1 is ok as this is not an instantitable type*/
6755 klass->sizes.element_size = -1;
6757 klass->sizes.element_size = mono_class_array_element_size (eclass);
6759 mono_class_setup_supertypes (klass);
6761 if (eclass->generic_class)
6762 mono_class_init (eclass);
6763 if (!eclass->size_inited)
6764 mono_class_setup_fields (eclass);
6765 if (mono_class_has_failure (eclass)) /*FIXME we fail the array type, but we have to let other fields be set.*/
6766 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
6768 klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6772 if (eclass->enumtype)
6773 klass->cast_class = eclass->element_class;
6775 klass->cast_class = eclass;
6777 switch (klass->cast_class->byval_arg.type) {
6779 klass->cast_class = mono_defaults.byte_class;
6782 klass->cast_class = mono_defaults.int16_class;
6785 #if SIZEOF_VOID_P == 4
6789 klass->cast_class = mono_defaults.int32_class;
6792 #if SIZEOF_VOID_P == 8
6796 klass->cast_class = mono_defaults.int64_class;
6802 klass->element_class = eclass;
6804 if ((rank > 1) || bounded) {
6805 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6806 klass->byval_arg.type = MONO_TYPE_ARRAY;
6807 klass->byval_arg.data.array = at;
6808 at->eklass = eclass;
6810 /* FIXME: complete.... */
6812 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6813 klass->byval_arg.data.klass = eclass;
6815 klass->this_arg = klass->byval_arg;
6816 klass->this_arg.byref = 1;
6821 klass->generic_container = eclass->generic_container;
6823 if (rank == 1 && !bounded) {
6824 MonoClass *prev_class;
6826 mono_os_mutex_lock (&image->szarray_cache_lock);
6827 prev_class = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6829 /* Someone got in before us */
6832 g_hash_table_insert (image->szarray_cache, eclass, klass);
6833 mono_os_mutex_unlock (&image->szarray_cache_lock);
6835 list = g_slist_append (rootlist, klass);
6836 g_hash_table_insert (image->array_cache, eclass, list);
6839 mono_loader_unlock ();
6841 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6847 * mono_array_class_get:
6848 * @element_class: element class
6849 * @rank: the dimension of the array class
6851 * Returns: A class object describing the array with element type @element_type and
6855 mono_array_class_get (MonoClass *eclass, guint32 rank)
6857 return mono_bounded_array_class_get (eclass, rank, FALSE);
6861 * mono_class_instance_size:
6864 * Use to get the size of a class in bytes.
6866 * Returns: The size of an object instance
6869 mono_class_instance_size (MonoClass *klass)
6871 if (!klass->size_inited)
6872 mono_class_init (klass);
6874 return klass->instance_size;
6878 * mono_class_min_align:
6881 * Use to get the computed minimum alignment requirements for the specified class.
6883 * Returns: minimm alignment requirements
6886 mono_class_min_align (MonoClass *klass)
6888 if (!klass->size_inited)
6889 mono_class_init (klass);
6891 return klass->min_align;
6895 * mono_class_value_size:
6898 * This function is used for value types, and return the
6899 * space and the alignment to store that kind of value object.
6901 * Returns: the size of a value of kind @klass
6904 mono_class_value_size (MonoClass *klass, guint32 *align)
6908 /* fixme: check disable, because we still have external revereces to
6909 * mscorlib and Dummy Objects
6911 /*g_assert (klass->valuetype);*/
6913 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6916 *align = klass->min_align;
6922 * mono_class_data_size:
6925 * Returns: The size of the static class data
6928 mono_class_data_size (MonoClass *klass)
6931 mono_class_init (klass);
6932 /* This can happen with dynamically created types */
6933 if (!klass->fields_inited)
6934 mono_class_setup_fields_locking (klass);
6936 /* in arrays, sizes.class_size is unioned with element_size
6937 * and arrays have no static fields
6941 return klass->sizes.class_size;
6945 * Auxiliary routine to mono_class_get_field
6947 * Takes a field index instead of a field token.
6949 static MonoClassField *
6950 mono_class_get_field_idx (MonoClass *klass, int idx)
6952 mono_class_setup_fields_locking (klass);
6953 if (mono_class_has_failure (klass))
6957 if (klass->image->uncompressed_metadata) {
6959 * klass->field.first points to the FieldPtr table, while idx points into the
6960 * Field table, so we have to do a search.
6962 /*FIXME this is broken for types with multiple fields with the same name.*/
6963 const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6966 for (i = 0; i < klass->field.count; ++i)
6967 if (mono_field_get_name (&klass->fields [i]) == name)
6968 return &klass->fields [i];
6969 g_assert_not_reached ();
6971 if (klass->field.count) {
6972 if ((idx >= klass->field.first) && (idx < klass->field.first + klass->field.count)){
6973 return &klass->fields [idx - klass->field.first];
6977 klass = klass->parent;
6983 * mono_class_get_field:
6984 * @class: the class to lookup the field.
6985 * @field_token: the field token
6987 * Returns: A MonoClassField representing the type and offset of
6988 * the field, or a NULL value if the field does not belong to this
6992 mono_class_get_field (MonoClass *klass, guint32 field_token)
6994 int idx = mono_metadata_token_index (field_token);
6996 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6998 return mono_class_get_field_idx (klass, idx - 1);
7002 * mono_class_get_field_from_name:
7003 * @klass: the class to lookup the field.
7004 * @name: the field name
7006 * Search the class @klass and it's parents for a field with the name @name.
7008 * Returns: The MonoClassField pointer of the named field or NULL
7011 mono_class_get_field_from_name (MonoClass *klass, const char *name)
7013 return mono_class_get_field_from_name_full (klass, name, NULL);
7017 * mono_class_get_field_from_name_full:
7018 * @klass: the class to lookup the field.
7019 * @name: the field name
7020 * @type: the type of the fields. This optional.
7022 * Search the class @klass and it's parents for a field with the name @name and type @type.
7024 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
7025 * of its generic type definition.
7027 * Returns: The MonoClassField pointer of the named field or NULL
7030 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
7034 mono_class_setup_fields_locking (klass);
7035 if (mono_class_has_failure (klass))
7039 for (i = 0; i < klass->field.count; ++i) {
7040 MonoClassField *field = &klass->fields [i];
7042 if (strcmp (name, mono_field_get_name (field)) != 0)
7046 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
7047 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
7052 klass = klass->parent;
7058 * mono_class_get_field_token:
7059 * @field: the field we need the token of
7061 * Get the token of a field. Note that the tokesn is only valid for the image
7062 * the field was loaded from. Don't use this function for fields in dynamic types.
7064 * Returns: The token representing the field in the image it was loaded from.
7067 mono_class_get_field_token (MonoClassField *field)
7069 MonoClass *klass = field->parent;
7072 mono_class_setup_fields_locking (klass);
7077 for (i = 0; i < klass->field.count; ++i) {
7078 if (&klass->fields [i] == field) {
7079 int idx = klass->field.first + i + 1;
7081 if (klass->image->uncompressed_metadata)
7082 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
7083 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
7086 klass = klass->parent;
7089 g_assert_not_reached ();
7094 mono_field_get_index (MonoClassField *field)
7096 int index = field - field->parent->fields;
7098 g_assert (index >= 0 && index < field->parent->field.count);
7104 * mono_class_get_field_default_value:
7106 * Return the default value of the field as a pointer into the metadata blob.
7109 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
7112 guint32 constant_cols [MONO_CONSTANT_SIZE];
7114 MonoClass *klass = field->parent;
7116 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7118 if (!klass->ext || !klass->ext->field_def_values) {
7119 MonoFieldDefaultValue *def_values;
7121 mono_class_alloc_ext (klass);
7123 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
7125 mono_image_lock (klass->image);
7126 mono_memory_barrier ();
7127 if (!klass->ext->field_def_values)
7128 klass->ext->field_def_values = def_values;
7129 mono_image_unlock (klass->image);
7132 field_index = mono_field_get_index (field);
7134 if (!klass->ext->field_def_values [field_index].data) {
7135 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7139 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7141 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7142 klass->ext->field_def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7143 klass->ext->field_def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7146 *def_type = klass->ext->field_def_values [field_index].def_type;
7147 return klass->ext->field_def_values [field_index].data;
7151 mono_property_get_index (MonoProperty *prop)
7153 int index = prop - prop->parent->ext->properties;
7155 g_assert (index >= 0 && index < prop->parent->ext->property.count);
7161 * mono_class_get_property_default_value:
7163 * Return the default value of the field as a pointer into the metadata blob.
7166 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7169 guint32 constant_cols [MONO_CONSTANT_SIZE];
7170 MonoClass *klass = property->parent;
7172 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7174 * We don't cache here because it is not used by C# so it's quite rare, but
7175 * we still do the lookup in klass->ext because that is where the data
7176 * is stored for dynamic assemblies.
7179 if (image_is_dynamic (klass->image)) {
7180 int prop_index = mono_property_get_index (property);
7181 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
7182 *def_type = klass->ext->prop_def_values [prop_index].def_type;
7183 return klass->ext->prop_def_values [prop_index].data;
7187 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7191 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7192 *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7193 return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7197 mono_class_get_event_token (MonoEvent *event)
7199 MonoClass *klass = event->parent;
7204 for (i = 0; i < klass->ext->event.count; ++i) {
7205 if (&klass->ext->events [i] == event)
7206 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
7209 klass = klass->parent;
7212 g_assert_not_reached ();
7217 * mono_class_get_property_from_name:
7219 * @name: name of the property to lookup in the specified class
7221 * Use this method to lookup a property in a class
7222 * Returns: the MonoProperty with the given name, or NULL if the property
7223 * does not exist on the @klass.
7226 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7230 gpointer iter = NULL;
7231 while ((p = mono_class_get_properties (klass, &iter))) {
7232 if (! strcmp (name, p->name))
7235 klass = klass->parent;
7241 * mono_class_get_property_token:
7242 * @prop: MonoProperty to query
7244 * Returns: The ECMA token for the specified property.
7247 mono_class_get_property_token (MonoProperty *prop)
7249 MonoClass *klass = prop->parent;
7253 gpointer iter = NULL;
7254 while ((p = mono_class_get_properties (klass, &iter))) {
7255 if (&klass->ext->properties [i] == prop)
7256 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
7260 klass = klass->parent;
7263 g_assert_not_reached ();
7268 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7270 const char *name, *nspace;
7271 if (image_is_dynamic (image))
7272 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7274 switch (type_token & 0xff000000){
7275 case MONO_TOKEN_TYPE_DEF: {
7276 guint32 cols [MONO_TYPEDEF_SIZE];
7277 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7278 guint tidx = mono_metadata_token_index (type_token);
7280 if (tidx > tt->rows)
7281 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7283 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7284 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7285 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7286 if (strlen (nspace) == 0)
7287 return g_strdup_printf ("%s", name);
7289 return g_strdup_printf ("%s.%s", nspace, name);
7292 case MONO_TOKEN_TYPE_REF: {
7294 guint32 cols [MONO_TYPEREF_SIZE];
7295 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7296 guint tidx = mono_metadata_token_index (type_token);
7299 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7301 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7302 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7303 mono_error_cleanup (&error);
7307 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7308 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7309 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7310 if (strlen (nspace) == 0)
7311 return g_strdup_printf ("%s", name);
7313 return g_strdup_printf ("%s.%s", nspace, name);
7316 case MONO_TOKEN_TYPE_SPEC:
7317 return g_strdup_printf ("Typespec 0x%08x", type_token);
7319 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7324 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7326 if (image_is_dynamic (image))
7327 return g_strdup_printf ("DynamicAssembly %s", image->name);
7329 switch (type_token & 0xff000000){
7330 case MONO_TOKEN_TYPE_DEF:
7331 if (image->assembly)
7332 return mono_stringify_assembly_name (&image->assembly->aname);
7333 else if (image->assembly_name)
7334 return g_strdup (image->assembly_name);
7335 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7336 case MONO_TOKEN_TYPE_REF: {
7338 MonoAssemblyName aname;
7339 guint32 cols [MONO_TYPEREF_SIZE];
7340 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7341 guint32 idx = mono_metadata_token_index (type_token);
7344 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7346 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7347 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7348 mono_error_cleanup (&error);
7351 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7353 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7354 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7355 case MONO_RESOLUTION_SCOPE_MODULE:
7357 return g_strdup ("");
7358 case MONO_RESOLUTION_SCOPE_MODULEREF:
7360 return g_strdup ("");
7361 case MONO_RESOLUTION_SCOPE_TYPEREF:
7363 return g_strdup ("");
7364 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7365 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7366 return mono_stringify_assembly_name (&aname);
7368 g_assert_not_reached ();
7372 case MONO_TOKEN_TYPE_SPEC:
7374 return g_strdup ("");
7376 g_assert_not_reached ();
7383 * mono_class_get_full:
7384 * @image: the image where the class resides
7385 * @type_token: the token for the class
7386 * @context: the generic context used to evaluate generic instantiations in
7387 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7389 * Returns: The MonoClass that represents @type_token in @image
7392 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7396 klass = mono_class_get_checked (image, type_token, &error);
7398 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7399 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7401 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7407 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7411 mono_error_init (error);
7412 klass = mono_class_get_checked (image, type_token, error);
7414 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7415 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7420 * mono_class_get_checked:
7421 * @image: the image where the class resides
7422 * @type_token: the token for the class
7423 * @error: error object to return any error
7425 * Returns: The MonoClass that represents @type_token in @image, or NULL on error.
7428 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7430 MonoClass *klass = NULL;
7432 mono_error_init (error);
7434 if (image_is_dynamic (image)) {
7435 int table = mono_metadata_token_table (type_token);
7437 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7438 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7441 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
7445 switch (type_token & 0xff000000){
7446 case MONO_TOKEN_TYPE_DEF:
7447 klass = mono_class_create_from_typedef (image, type_token, error);
7449 case MONO_TOKEN_TYPE_REF:
7450 klass = mono_class_from_typeref_checked (image, type_token, error);
7452 case MONO_TOKEN_TYPE_SPEC:
7453 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7456 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7460 /* Generic case, should be avoided for when a better error is possible. */
7461 if (!klass && mono_error_ok (error)) {
7462 char *name = mono_class_name_from_token (image, type_token);
7463 char *assembly = mono_assembly_name_from_token (image, type_token);
7464 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7472 * mono_type_get_checked:
7473 * @image: the image where the type resides
7474 * @type_token: the token for the type
7475 * @context: the generic context used to evaluate generic instantiations in
7476 * @error: Error handling context
7478 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7480 * Returns: The MonoType that represents @type_token in @image
7483 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7485 MonoType *type = NULL;
7486 gboolean inflated = FALSE;
7488 mono_error_init (error);
7490 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7491 if (image_is_dynamic (image)) {
7492 MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
7493 return_val_if_nok (error, NULL);
7494 return mono_class_get_type (klass);
7497 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7498 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7505 return mono_class_get_type (klass);
7508 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7515 MonoType *tmp = type;
7516 type = mono_class_get_type (mono_class_from_mono_type (type));
7517 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7518 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7519 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7521 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7523 if (type->type != tmp->type)
7526 mono_metadata_free_type (tmp);
7533 * @image: image where the class token will be looked up.
7534 * @type_token: a type token from the image
7536 * Returns the MonoClass with the given @type_token on the @image
7539 mono_class_get (MonoImage *image, guint32 type_token)
7541 return mono_class_get_full (image, type_token, NULL);
7545 * mono_image_init_name_cache:
7547 * Initializes the class name cache stored in image->name_cache.
7549 * LOCKING: Acquires the corresponding image lock.
7552 mono_image_init_name_cache (MonoImage *image)
7554 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7555 guint32 cols [MONO_TYPEDEF_SIZE];
7558 guint32 i, visib, nspace_index;
7559 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7561 if (image->name_cache)
7564 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7566 if (image_is_dynamic (image)) {
7567 mono_image_lock (image);
7568 if (image->name_cache) {
7569 /* Somebody initialized it before us */
7570 g_hash_table_destroy (the_name_cache);
7572 mono_atomic_store_release (&image->name_cache, the_name_cache);
7574 mono_image_unlock (image);
7578 /* Temporary hash table to avoid lookups in the nspace_table */
7579 name_cache2 = g_hash_table_new (NULL, NULL);
7581 for (i = 1; i <= t->rows; ++i) {
7582 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7583 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7585 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7586 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7588 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7590 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7591 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7593 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7594 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7595 if (!nspace_table) {
7596 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7597 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7598 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7601 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7604 /* Load type names from EXPORTEDTYPES table */
7606 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7607 guint32 cols [MONO_EXP_TYPE_SIZE];
7610 for (i = 0; i < t->rows; ++i) {
7611 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7613 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7614 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7618 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7619 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7621 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7622 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7623 if (!nspace_table) {
7624 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7625 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7626 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7629 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7633 g_hash_table_destroy (name_cache2);
7635 mono_image_lock (image);
7636 if (image->name_cache) {
7637 /* Somebody initialized it before us */
7638 g_hash_table_destroy (the_name_cache);
7640 mono_atomic_store_release (&image->name_cache, the_name_cache);
7642 mono_image_unlock (image);
7645 /*FIXME Only dynamic assemblies should allow this operation.*/
7647 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7648 const char *name, guint32 index)
7650 GHashTable *nspace_table;
7651 GHashTable *name_cache;
7654 mono_image_init_name_cache (image);
7655 mono_image_lock (image);
7657 name_cache = image->name_cache;
7658 if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7659 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7660 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7663 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7664 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7666 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7668 mono_image_unlock (image);
7677 find_nocase (gpointer key, gpointer value, gpointer user_data)
7679 char *name = (char*)key;
7680 FindUserData *data = (FindUserData*)user_data;
7682 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7683 data->value = value;
7687 * mono_class_from_name_case:
7688 * @image: The MonoImage where the type is looked up in
7689 * @name_space: the type namespace
7690 * @name: the type short name.
7691 * @deprecated: use the mono_class_from_name_case_checked variant instead.
7693 * Obtains a MonoClass with a given namespace and a given name which
7694 * is located in the given MonoImage. The namespace and name
7695 * lookups are case insensitive.
7698 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7701 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7702 mono_error_cleanup (&error);
7708 * mono_class_from_name_case:
7709 * @image: The MonoImage where the type is looked up in
7710 * @name_space: the type namespace
7711 * @name: the type short name.
7714 * Obtains a MonoClass with a given namespace and a given name which
7715 * is located in the given MonoImage. The namespace and name
7716 * lookups are case insensitive.
7718 * Returns: The MonoClass if the given namespace and name were found, or NULL if it
7719 * was not found. The @error object will contain information about the problem
7723 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7725 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7726 guint32 cols [MONO_TYPEDEF_SIZE];
7731 mono_error_init (error);
7733 if (image_is_dynamic (image)) {
7735 FindUserData user_data;
7737 mono_image_init_name_cache (image);
7738 mono_image_lock (image);
7740 user_data.key = name_space;
7741 user_data.value = NULL;
7742 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7744 if (user_data.value) {
7745 GHashTable *nspace_table = (GHashTable*)user_data.value;
7747 user_data.key = name;
7748 user_data.value = NULL;
7750 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7752 if (user_data.value)
7753 token = GPOINTER_TO_UINT (user_data.value);
7756 mono_image_unlock (image);
7759 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7765 /* add a cache if needed */
7766 for (i = 1; i <= t->rows; ++i) {
7767 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7768 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7770 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7771 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7773 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7775 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7776 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7777 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7778 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7784 return_nested_in (MonoClass *klass, char *nested)
7787 char *s = strchr (nested, '/');
7788 gpointer iter = NULL;
7795 while ((found = mono_class_get_nested_types (klass, &iter))) {
7796 if (strcmp (found->name, nested) == 0) {
7798 return return_nested_in (found, s);
7806 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7808 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7809 MonoImage *file_image;
7813 mono_error_init (error);
7816 * The EXPORTEDTYPES table only contains public types, so have to search the
7818 * Note: image->modules contains the contents of the MODULEREF table, while
7819 * the real module list is in the FILE table.
7821 for (i = 0; i < file_table->rows; i++) {
7822 guint32 cols [MONO_FILE_SIZE];
7823 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7824 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7827 file_image = mono_image_load_file_for_image_checked (image, i + 1, error);
7829 klass = mono_class_from_name_checked (file_image, name_space, name, error);
7830 if (klass || !is_ok (error))
7839 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7841 GHashTable *nspace_table;
7842 MonoImage *loaded_image;
7849 mono_error_init (error);
7851 // Checking visited images avoids stack overflows when cyclic references exist.
7852 if (g_hash_table_lookup (visited_images, image))
7855 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7857 if ((nested = strchr (name, '/'))) {
7858 int pos = nested - name;
7859 int len = strlen (name);
7862 memcpy (buf, name, len + 1);
7864 nested = buf + pos + 1;
7868 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7869 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7870 gboolean res = get_class_from_name (image, name_space, name, &klass);
7873 klass = search_modules (image, name_space, name, error);
7878 return klass ? return_nested_in (klass, nested) : NULL;
7884 mono_image_init_name_cache (image);
7885 mono_image_lock (image);
7887 nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7890 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7892 mono_image_unlock (image);
7894 if (!token && image_is_dynamic (image) && image->modules) {
7895 /* Search modules as well */
7896 for (i = 0; i < image->module_count; ++i) {
7897 MonoImage *module = image->modules [i];
7899 klass = mono_class_from_name_checked (module, name_space, name, error);
7900 if (klass || !is_ok (error))
7906 klass = search_modules (image, name_space, name, error);
7907 if (klass || !is_ok (error))
7912 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7913 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7914 guint32 cols [MONO_EXP_TYPE_SIZE];
7917 idx = mono_metadata_token_index (token);
7919 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7921 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7922 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7923 loaded_image = mono_assembly_load_module_checked (image->assembly, impl >> MONO_IMPLEMENTATION_BITS, error);
7926 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7928 return klass ? return_nested_in (klass, nested) : NULL;
7930 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7931 guint32 assembly_idx;
7933 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7935 mono_assembly_load_reference (image, assembly_idx - 1);
7936 g_assert (image->references [assembly_idx - 1]);
7937 if (image->references [assembly_idx - 1] == (gpointer)-1)
7939 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
7941 return klass ? return_nested_in (klass, nested) : NULL;
7944 g_assert_not_reached ();
7948 token = MONO_TOKEN_TYPE_DEF | token;
7950 klass = mono_class_get_checked (image, token, error);
7952 return return_nested_in (klass, nested);
7957 * mono_class_from_name_checked:
7958 * @image: The MonoImage where the type is looked up in
7959 * @name_space: the type namespace
7960 * @name: the type short name.
7962 * Obtains a MonoClass with a given namespace and a given name which
7963 * is located in the given MonoImage.
7965 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
7966 * set if the class was not found or it will return NULL and set the error if there was a loading error.
7969 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7972 GHashTable *visited_images;
7974 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7976 klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
7978 g_hash_table_destroy (visited_images);
7984 * mono_class_from_name:
7985 * @image: The MonoImage where the type is looked up in
7986 * @name_space: the type namespace
7987 * @name: the type short name.
7989 * Obtains a MonoClass with a given namespace and a given name which
7990 * is located in the given MonoImage.
7992 * To reference nested classes, use the "/" character as a separator.
7993 * For example use "Foo/Bar" to reference the class Bar that is nested
7994 * inside Foo, like this: "class Foo { class Bar {} }".
7997 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
8002 klass = mono_class_from_name_checked (image, name_space, name, &error);
8003 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
8009 * mono_class_load_from_name:
8010 * @image: The MonoImage where the type is looked up in
8011 * @name_space: the type namespace
8012 * @name: the type short name.
8014 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
8015 * This function should be used by the runtime for critical types to which there's no way to recover but crash
8016 * If they are missing. Thing of System.Object or System.String.
8019 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
8024 klass = mono_class_from_name_checked (image, name_space, name, &error);
8026 g_error ("Runtime critical type %s.%s not found", name_space, name);
8027 if (!mono_error_ok (&error))
8028 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8033 * mono_class_try_load_from_name:
8034 * @image: The MonoImage where the type is looked up in
8035 * @name_space: the type namespace
8036 * @name: the type short name.
8038 * This function tries to load a type, returning the class was found or NULL otherwise.
8039 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
8041 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
8042 * a type that we would otherwise assume to be available but was not due some error.
8046 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
8051 klass = mono_class_from_name_checked (image, name_space, name, &error);
8052 if (!mono_error_ok (&error))
8053 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8059 * mono_class_is_subclass_of:
8060 * @klass: class to probe if it is a subclass of another one
8061 * @klassc: the class we suspect is the base class
8062 * @check_interfaces: whether we should perform interface checks
8064 * This method determines whether @klass is a subclass of @klassc.
8066 * If the @check_interfaces flag is set, then if @klassc is an interface
8067 * this method return TRUE if the @klass implements the interface or
8068 * if @klass is an interface, if one of its base classes is @klass.
8070 * If @check_interfaces is false then, then if @klass is not an interface
8071 * then it returns TRUE if the @klass is a subclass of @klassc.
8073 * if @klass is an interface and @klassc is System.Object, then this function
8078 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
8079 gboolean check_interfaces)
8081 /* FIXME test for interfaces with variant generic arguments */
8082 mono_class_init (klass);
8083 mono_class_init (klassc);
8085 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
8086 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
8088 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
8091 for (i = 0; i < klass->interface_count; i ++) {
8092 MonoClass *ic = klass->interfaces [i];
8097 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
8102 * MS.NET thinks interfaces are a subclass of Object, so we think it as
8105 if (klassc == mono_defaults.object_class)
8112 mono_type_is_generic_argument (MonoType *type)
8114 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
8118 mono_class_has_variant_generic_params (MonoClass *klass)
8121 MonoGenericContainer *container;
8123 if (!klass->generic_class)
8126 container = klass->generic_class->container_class->generic_container;
8128 for (i = 0; i < container->type_argc; ++i)
8129 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8136 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8138 if (target == candidate)
8141 if (check_for_reference_conv &&
8142 mono_type_is_generic_argument (&target->byval_arg) &&
8143 mono_type_is_generic_argument (&candidate->byval_arg)) {
8144 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8145 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8147 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8150 if (!mono_class_is_assignable_from (target, candidate))
8156 * @container the generic container from the GTD
8157 * @klass: the class to be assigned to
8158 * @oklass: the source class
8160 * Both @klass and @oklass must be instances of the same generic interface.
8162 * Returns: TRUE if @klass can be assigned to a @klass variable
8165 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8168 MonoType **klass_argv, **oklass_argv;
8169 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8170 MonoGenericContainer *container = klass_gtd->generic_container;
8172 if (klass == oklass)
8175 /*Viable candidates are instances of the same generic interface*/
8176 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8179 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8180 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8182 for (j = 0; j < container->type_argc; ++j) {
8183 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8184 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8186 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8190 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8191 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8193 if (param1_class != param2_class) {
8194 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8195 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8197 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8198 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8208 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8210 MonoGenericParam *gparam, *ogparam;
8211 MonoGenericParamInfo *tinfo, *cinfo;
8212 MonoClass **candidate_class;
8213 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8216 if (target == candidate)
8218 if (target->byval_arg.type != candidate->byval_arg.type)
8221 gparam = target->byval_arg.data.generic_param;
8222 ogparam = candidate->byval_arg.data.generic_param;
8223 tinfo = mono_generic_param_info (gparam);
8224 cinfo = mono_generic_param_info (ogparam);
8226 class_constraint_satisfied = FALSE;
8227 valuetype_constraint_satisfied = FALSE;
8229 /*candidate must have a super set of target's special constraints*/
8230 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8231 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8233 if (cinfo->constraints) {
8234 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8235 MonoClass *cc = *candidate_class;
8237 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8238 class_constraint_satisfied = TRUE;
8239 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8240 valuetype_constraint_satisfied = TRUE;
8243 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8244 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8246 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8248 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8250 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8251 valuetype_constraint_satisfied)) {
8256 /*candidate type constraints must be a superset of target's*/
8257 if (tinfo->constraints) {
8258 MonoClass **target_class;
8259 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8260 MonoClass *tc = *target_class;
8263 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8264 * check it's constraints since it satisfy the constraint by itself.
8266 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8269 if (!cinfo->constraints)
8272 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8273 MonoClass *cc = *candidate_class;
8275 if (mono_class_is_assignable_from (tc, cc))
8279 * This happens when we have the following:
8281 * Bar<K> where K : IFace
8282 * Foo<T, U> where T : U where U : IFace
8284 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8287 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8288 if (mono_gparam_is_assignable_from (target, cc))
8292 if (!*candidate_class)
8297 /*candidate itself must have a constraint that satisfy target*/
8298 if (cinfo->constraints) {
8299 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8300 MonoClass *cc = *candidate_class;
8301 if (mono_class_is_assignable_from (target, cc))
8309 * mono_class_is_assignable_from:
8310 * @klass: the class to be assigned to
8311 * @oklass: the source class
8313 * Returns: TRUE if an instance of object oklass can be assigned to an
8314 * instance of object @klass
8317 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8320 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8322 mono_class_init (klass);
8324 if (!oklass->inited)
8325 mono_class_init (oklass);
8327 if (mono_class_has_failure (klass) || mono_class_has_failure (oklass))
8330 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8331 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8333 return mono_gparam_is_assignable_from (klass, oklass);
8336 if (MONO_CLASS_IS_INTERFACE (klass)) {
8337 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8338 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8339 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8343 for (i = 0; constraints [i]; ++i) {
8344 if (mono_class_is_assignable_from (klass, constraints [i]))
8352 /* interface_offsets might not be set for dynamic classes */
8353 if (oklass->ref_info_handle && !oklass->interface_bitmap) {
8355 * oklass might be a generic type parameter but they have
8356 * interface_offsets set.
8358 gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8359 if (!is_ok (&error)) {
8360 mono_error_cleanup (&error);
8365 if (!oklass->interface_bitmap)
8366 /* Happens with generic instances of not-yet created dynamic types */
8368 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8371 if (mono_class_has_variant_generic_params (klass)) {
8373 mono_class_setup_interfaces (oklass, &error);
8374 if (!mono_error_ok (&error)) {
8375 mono_error_cleanup (&error);
8379 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8380 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8381 MonoClass *iface = oklass->interfaces_packed [i];
8383 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8388 } else if (klass->delegate) {
8389 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8391 }else if (klass->rank) {
8392 MonoClass *eclass, *eoclass;
8394 if (oklass->rank != klass->rank)
8397 /* vectors vs. one dimensional arrays */
8398 if (oklass->byval_arg.type != klass->byval_arg.type)
8401 eclass = klass->cast_class;
8402 eoclass = oklass->cast_class;
8405 * a is b does not imply a[] is b[] when a is a valuetype, and
8406 * b is a reference type.
8409 if (eoclass->valuetype) {
8410 if ((eclass == mono_defaults.enum_class) ||
8411 (eclass == mono_defaults.enum_class->parent) ||
8412 (eclass == mono_defaults.object_class))
8416 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8417 } else if (mono_class_is_nullable (klass)) {
8418 if (mono_class_is_nullable (oklass))
8419 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8421 return mono_class_is_assignable_from (klass->cast_class, oklass);
8422 } else if (klass == mono_defaults.object_class)
8425 return mono_class_has_parent (oklass, klass);
8428 /*Check if @oklass is variant compatible with @klass.*/
8430 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8433 MonoType **klass_argv, **oklass_argv;
8434 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8435 MonoGenericContainer *container = klass_gtd->generic_container;
8437 /*Viable candidates are instances of the same generic interface*/
8438 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8441 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8442 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8444 for (j = 0; j < container->type_argc; ++j) {
8445 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8446 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8448 if (param1_class->valuetype != param2_class->valuetype)
8452 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8453 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8455 if (param1_class != param2_class) {
8456 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8457 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8459 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8460 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8468 /*Check if @candidate implements the interface @target*/
8470 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8474 gboolean is_variant = mono_class_has_variant_generic_params (target);
8476 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8477 if (mono_class_is_variant_compatible_slow (target, candidate))
8482 if (candidate == target)
8485 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8486 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8487 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (candidate);
8489 if (tb && tb->interfaces) {
8490 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8491 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8492 MonoClass *iface_class;
8494 /* we can't realize the type here since it can do pretty much anything. */
8497 iface_class = mono_class_from_mono_type (iface->type);
8498 if (iface_class == target)
8500 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8502 if (mono_class_implement_interface_slow (target, iface_class))
8507 /*setup_interfaces don't mono_class_init anything*/
8508 /*FIXME this doesn't handle primitive type arrays.
8509 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8510 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8512 mono_class_setup_interfaces (candidate, &error);
8513 if (!mono_error_ok (&error)) {
8514 mono_error_cleanup (&error);
8518 for (i = 0; i < candidate->interface_count; ++i) {
8519 if (candidate->interfaces [i] == target)
8522 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8525 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8529 candidate = candidate->parent;
8530 } while (candidate);
8536 * Check if @oklass can be assigned to @klass.
8537 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8540 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8542 if (candidate == target)
8544 if (target == mono_defaults.object_class)
8547 if (mono_class_has_parent (candidate, target))
8550 /*If target is not an interface there is no need to check them.*/
8551 if (MONO_CLASS_IS_INTERFACE (target))
8552 return mono_class_implement_interface_slow (target, candidate);
8554 if (target->delegate && mono_class_has_variant_generic_params (target))
8555 return mono_class_is_variant_compatible (target, candidate, FALSE);
8558 MonoClass *eclass, *eoclass;
8560 if (target->rank != candidate->rank)
8563 /* vectors vs. one dimensional arrays */
8564 if (target->byval_arg.type != candidate->byval_arg.type)
8567 eclass = target->cast_class;
8568 eoclass = candidate->cast_class;
8571 * a is b does not imply a[] is b[] when a is a valuetype, and
8572 * b is a reference type.
8575 if (eoclass->valuetype) {
8576 if ((eclass == mono_defaults.enum_class) ||
8577 (eclass == mono_defaults.enum_class->parent) ||
8578 (eclass == mono_defaults.object_class))
8582 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8584 /*FIXME properly handle nullables */
8585 /*FIXME properly handle (M)VAR */
8590 * mono_class_get_cctor:
8591 * @klass: A MonoClass pointer
8593 * Returns: The static constructor of @klass if it exists, NULL otherwise.
8596 mono_class_get_cctor (MonoClass *klass)
8598 MonoCachedClassInfo cached_info;
8600 if (image_is_dynamic (klass->image)) {
8602 * has_cctor is not set for these classes because mono_class_init () is
8605 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8608 if (!klass->has_cctor)
8611 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8613 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8614 if (!mono_error_ok (&error))
8615 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8619 if (klass->generic_class && !klass->methods)
8620 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8622 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8626 * mono_class_get_finalizer:
8627 * @klass: The MonoClass pointer
8629 * Returns: The finalizer method of @klass if it exists, NULL otherwise.
8632 mono_class_get_finalizer (MonoClass *klass)
8634 MonoCachedClassInfo cached_info;
8637 mono_class_init (klass);
8638 if (!mono_class_has_finalizer (klass))
8641 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8643 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8644 if (!mono_error_ok (&error))
8645 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8648 mono_class_setup_vtable (klass);
8649 return klass->vtable [finalize_slot];
8654 * mono_class_needs_cctor_run:
8655 * @klass: the MonoClass pointer
8656 * @caller: a MonoMethod describing the caller
8658 * Determines whenever the class has a static constructor and whenever it
8659 * needs to be called when executing CALLER.
8662 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8666 method = mono_class_get_cctor (klass);
8668 return (method == caller) ? FALSE : TRUE;
8674 * mono_class_array_element_size:
8677 * Returns: The number of bytes an element of type @klass
8678 * uses when stored into an array.
8681 mono_class_array_element_size (MonoClass *klass)
8683 MonoType *type = &klass->byval_arg;
8686 switch (type->type) {
8689 case MONO_TYPE_BOOLEAN:
8693 case MONO_TYPE_CHAR:
8702 case MONO_TYPE_CLASS:
8703 case MONO_TYPE_STRING:
8704 case MONO_TYPE_OBJECT:
8705 case MONO_TYPE_SZARRAY:
8706 case MONO_TYPE_ARRAY:
8707 return sizeof (gpointer);
8712 case MONO_TYPE_VALUETYPE:
8713 if (type->data.klass->enumtype) {
8714 type = mono_class_enum_basetype (type->data.klass);
8715 klass = klass->element_class;
8718 return mono_class_instance_size (klass) - sizeof (MonoObject);
8719 case MONO_TYPE_GENERICINST:
8720 type = &type->data.generic_class->container_class->byval_arg;
8723 case MONO_TYPE_MVAR: {
8726 return mono_type_size (type, &align);
8728 case MONO_TYPE_VOID:
8732 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8738 * mono_array_element_size:
8739 * @ac: pointer to a #MonoArrayClass
8741 * Returns: The size of single array element.
8744 mono_array_element_size (MonoClass *ac)
8746 g_assert (ac->rank);
8747 return ac->sizes.element_size;
8751 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8752 MonoGenericContext *context)
8755 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8756 g_assert (mono_error_ok (&error));
8761 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8762 MonoGenericContext *context, MonoError *error)
8764 mono_error_init (error);
8766 if (image_is_dynamic (image)) {
8767 MonoClass *tmp_handle_class;
8768 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
8770 mono_error_assert_ok (error);
8771 g_assert (tmp_handle_class);
8773 *handle_class = tmp_handle_class;
8775 if (tmp_handle_class == mono_defaults.typehandle_class)
8776 return &((MonoClass*)obj)->byval_arg;
8781 switch (token & 0xff000000) {
8782 case MONO_TOKEN_TYPE_DEF:
8783 case MONO_TOKEN_TYPE_REF:
8784 case MONO_TOKEN_TYPE_SPEC: {
8787 *handle_class = mono_defaults.typehandle_class;
8788 type = mono_type_get_checked (image, token, context, error);
8792 mono_class_init (mono_class_from_mono_type (type));
8793 /* We return a MonoType* as handle */
8796 case MONO_TOKEN_FIELD_DEF: {
8798 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8800 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8804 *handle_class = mono_defaults.fieldhandle_class;
8805 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8809 mono_class_init (klass);
8810 return mono_class_get_field (klass, token);
8812 case MONO_TOKEN_METHOD_DEF:
8813 case MONO_TOKEN_METHOD_SPEC: {
8815 meth = mono_get_method_checked (image, token, NULL, context, error);
8817 *handle_class = mono_defaults.methodhandle_class;
8823 case MONO_TOKEN_MEMBER_REF: {
8824 guint32 cols [MONO_MEMBERREF_SIZE];
8826 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8827 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8828 mono_metadata_decode_blob_size (sig, &sig);
8829 if (*sig == 0x6) { /* it's a field */
8831 MonoClassField *field;
8832 field = mono_field_from_token_checked (image, token, &klass, context, error);
8834 *handle_class = mono_defaults.fieldhandle_class;
8838 meth = mono_get_method_checked (image, token, NULL, context, error);
8840 *handle_class = mono_defaults.methodhandle_class;
8845 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8851 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
8853 MonoClass *handle_class;
8854 mono_error_init (error);
8855 return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
8859 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
8861 return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
8864 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8867 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8869 get_cached_class_info = func;
8873 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8875 if (!get_cached_class_info)
8878 return get_cached_class_info (klass, res);
8882 mono_install_get_class_from_name (MonoGetClassFromName func)
8884 get_class_from_name = func;
8888 * mono_class_get_image:
8890 * Use this method to get the `MonoImage*` where this class came from.
8892 * Returns: The image where this class is defined.
8895 mono_class_get_image (MonoClass *klass)
8897 return klass->image;
8901 * mono_class_get_element_class:
8902 * @klass: the MonoClass to act on
8904 * Use this function to get the element class of an array.
8906 * Returns: The element class of an array.
8909 mono_class_get_element_class (MonoClass *klass)
8911 return klass->element_class;
8915 * mono_class_is_valuetype:
8916 * @klass: the MonoClass to act on
8918 * Use this method to determine if the provided `MonoClass*` represents a value type,
8919 * or a reference type.
8921 * Returns: TRUE if the MonoClass represents a ValueType, FALSE if it represents a reference type.
8924 mono_class_is_valuetype (MonoClass *klass)
8926 return klass->valuetype;
8930 * mono_class_is_enum:
8931 * @klass: the MonoClass to act on
8933 * Use this function to determine if the provided `MonoClass*` represents an enumeration.
8935 * Returns: TRUE if the MonoClass represents an enumeration.
8938 mono_class_is_enum (MonoClass *klass)
8940 return klass->enumtype;
8944 * mono_class_enum_basetype:
8945 * @klass: the MonoClass to act on
8947 * Use this function to get the underlying type for an enumeration value.
8949 * Returns: The underlying type representation for an enumeration.
8952 mono_class_enum_basetype (MonoClass *klass)
8954 if (klass->element_class == klass)
8955 /* SRE or broken types */
8958 return &klass->element_class->byval_arg;
8962 * mono_class_get_parent
8963 * @klass: the MonoClass to act on
8965 * Returns: The parent class for this class.
8968 mono_class_get_parent (MonoClass *klass)
8970 return klass->parent;
8974 * mono_class_get_nesting_type:
8975 * @klass: the MonoClass to act on
8977 * Use this function to obtain the class that the provided `MonoClass*` is nested on.
8979 * If the return is NULL, this indicates that this class is not nested.
8981 * Returns: The container type where this type is nested or NULL if this type is not a nested type.
8984 mono_class_get_nesting_type (MonoClass *klass)
8986 return klass->nested_in;
8990 * mono_class_get_rank:
8991 * @klass: the MonoClass to act on
8993 * Returns: The rank for the array (the number of dimensions).
8996 mono_class_get_rank (MonoClass *klass)
9002 * mono_class_get_flags:
9003 * @klass: the MonoClass to act on
9005 * The type flags from the TypeDef table from the metadata.
9006 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
9009 * Returns: The flags from the TypeDef table.
9012 mono_class_get_flags (MonoClass *klass)
9014 return klass->flags;
9018 * mono_class_get_name
9019 * @klass: the MonoClass to act on
9021 * Returns: The name of the class.
9024 mono_class_get_name (MonoClass *klass)
9030 * mono_class_get_namespace:
9031 * @klass: the MonoClass to act on
9033 * Returns: The namespace of the class.
9036 mono_class_get_namespace (MonoClass *klass)
9038 return klass->name_space;
9042 * mono_class_get_type:
9043 * @klass: the MonoClass to act on
9045 * This method returns the internal Type representation for the class.
9047 * Returns: The MonoType from the class.
9050 mono_class_get_type (MonoClass *klass)
9052 return &klass->byval_arg;
9056 * mono_class_get_type_token:
9057 * @klass: the MonoClass to act on
9059 * This method returns type token for the class.
9061 * Returns: The type token for the class.
9064 mono_class_get_type_token (MonoClass *klass)
9066 return klass->type_token;
9070 * mono_class_get_byref_type:
9071 * @klass: the MonoClass to act on
9076 mono_class_get_byref_type (MonoClass *klass)
9078 return &klass->this_arg;
9082 * mono_class_num_fields:
9083 * @klass: the MonoClass to act on
9085 * Returns: The number of static and instance fields in the class.
9088 mono_class_num_fields (MonoClass *klass)
9090 return klass->field.count;
9094 * mono_class_num_methods:
9095 * @klass: the MonoClass to act on
9097 * Returns: The number of methods in the class.
9100 mono_class_num_methods (MonoClass *klass)
9102 return klass->method.count;
9106 * mono_class_num_properties
9107 * @klass: the MonoClass to act on
9109 * Returns: The number of properties in the class.
9112 mono_class_num_properties (MonoClass *klass)
9114 mono_class_setup_properties (klass);
9116 return klass->ext->property.count;
9120 * mono_class_num_events:
9121 * @klass: the MonoClass to act on
9123 * Returns: The number of events in the class.
9126 mono_class_num_events (MonoClass *klass)
9128 mono_class_setup_events (klass);
9130 return klass->ext->event.count;
9134 * mono_class_get_fields:
9135 * @klass: the MonoClass to act on
9137 * This routine is an iterator routine for retrieving the fields in a class.
9139 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9140 * iterate over all of the elements. When no more values are
9141 * available, the return value is NULL.
9143 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
9146 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9148 MonoClassField* field;
9152 mono_class_setup_fields_locking (klass);
9153 if (mono_class_has_failure (klass))
9155 /* start from the first */
9156 if (klass->field.count) {
9157 *iter = &klass->fields [0];
9158 return &klass->fields [0];
9164 field = (MonoClassField *)*iter;
9166 if (field < &klass->fields [klass->field.count]) {
9174 * mono_class_get_methods
9175 * @klass: the MonoClass to act on
9177 * This routine is an iterator routine for retrieving the fields in a class.
9179 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9180 * iterate over all of the elements. When no more values are
9181 * available, the return value is NULL.
9183 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
9186 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9188 MonoMethod** method;
9192 mono_class_setup_methods (klass);
9195 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9196 * FIXME we should better report this error to the caller
9198 if (!klass->methods)
9200 /* start from the first */
9201 if (klass->method.count) {
9202 *iter = &klass->methods [0];
9203 return klass->methods [0];
9209 method = (MonoMethod **)*iter;
9211 if (method < &klass->methods [klass->method.count]) {
9219 * mono_class_get_virtual_methods:
9221 * Iterate over the virtual methods of KLASS.
9223 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9226 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9228 MonoMethod** method;
9231 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9233 mono_class_setup_methods (klass);
9235 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9236 * FIXME we should better report this error to the caller
9238 if (!klass->methods)
9240 /* start from the first */
9241 method = &klass->methods [0];
9243 method = (MonoMethod **)*iter;
9246 while (method < &klass->methods [klass->method.count]) {
9247 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9251 if (method < &klass->methods [klass->method.count]) {
9258 /* Search directly in metadata to avoid calling setup_methods () */
9259 MonoMethod *res = NULL;
9265 start_index = GPOINTER_TO_UINT (*iter);
9268 for (i = start_index; i < klass->method.count; ++i) {
9271 /* klass->method.first points into the methodptr table */
9272 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
9274 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9278 if (i < klass->method.count) {
9280 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9281 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9283 /* Add 1 here so the if (*iter) check fails */
9284 *iter = GUINT_TO_POINTER (i + 1);
9293 * mono_class_get_properties:
9294 * @klass: the MonoClass to act on
9296 * This routine is an iterator routine for retrieving the properties in a class.
9298 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9299 * iterate over all of the elements. When no more values are
9300 * available, the return value is NULL.
9302 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9305 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9307 MonoProperty* property;
9311 mono_class_setup_properties (klass);
9312 /* start from the first */
9313 if (klass->ext->property.count) {
9314 *iter = &klass->ext->properties [0];
9315 return (MonoProperty *)*iter;
9321 property = (MonoProperty *)*iter;
9323 if (property < &klass->ext->properties [klass->ext->property.count]) {
9325 return (MonoProperty *)*iter;
9331 * mono_class_get_events:
9332 * @klass: the MonoClass to act on
9334 * This routine is an iterator routine for retrieving the properties in a class.
9336 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9337 * iterate over all of the elements. When no more values are
9338 * available, the return value is NULL.
9340 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9343 mono_class_get_events (MonoClass* klass, gpointer *iter)
9349 mono_class_setup_events (klass);
9350 /* start from the first */
9351 if (klass->ext->event.count) {
9352 *iter = &klass->ext->events [0];
9353 return (MonoEvent *)*iter;
9359 event = (MonoEvent *)*iter;
9361 if (event < &klass->ext->events [klass->ext->event.count]) {
9363 return (MonoEvent *)*iter;
9369 * mono_class_get_interfaces
9370 * @klass: the MonoClass to act on
9372 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9374 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9375 * iterate over all of the elements. When no more values are
9376 * available, the return value is NULL.
9378 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9381 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9389 mono_class_init (klass);
9390 if (!klass->interfaces_inited) {
9391 mono_class_setup_interfaces (klass, &error);
9392 if (!mono_error_ok (&error)) {
9393 mono_error_cleanup (&error);
9397 /* start from the first */
9398 if (klass->interface_count) {
9399 *iter = &klass->interfaces [0];
9400 return klass->interfaces [0];
9406 iface = (MonoClass **)*iter;
9408 if (iface < &klass->interfaces [klass->interface_count]) {
9416 setup_nested_types (MonoClass *klass)
9419 GList *classes, *nested_classes, *l;
9422 if (klass->nested_classes_inited)
9425 if (!klass->type_token)
9426 klass->nested_classes_inited = TRUE;
9428 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9432 guint32 cols [MONO_NESTED_CLASS_SIZE];
9433 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9434 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9435 if (!mono_error_ok (&error)) {
9436 /*FIXME don't swallow the error message*/
9437 mono_error_cleanup (&error);
9439 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9443 classes = g_list_prepend (classes, nclass);
9445 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9448 mono_class_alloc_ext (klass);
9450 nested_classes = NULL;
9451 for (l = classes; l; l = l->next)
9452 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9453 g_list_free (classes);
9455 mono_image_lock (klass->image);
9457 mono_memory_barrier ();
9458 if (!klass->nested_classes_inited) {
9459 klass->ext->nested_classes = nested_classes;
9460 mono_memory_barrier ();
9461 klass->nested_classes_inited = TRUE;
9464 mono_image_unlock (klass->image);
9468 * mono_class_get_nested_types
9469 * @klass: the MonoClass to act on
9471 * This routine is an iterator routine for retrieving the nested types of a class.
9472 * This works only if @klass is non-generic, or a generic type definition.
9474 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9475 * iterate over all of the elements. When no more values are
9476 * available, the return value is NULL.
9478 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9481 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9487 if (!klass->nested_classes_inited)
9488 setup_nested_types (klass);
9491 /* start from the first */
9492 if (klass->ext && klass->ext->nested_classes) {
9493 *iter = klass->ext->nested_classes;
9494 return (MonoClass *)klass->ext->nested_classes->data;
9496 /* no nested types */
9500 item = (GList *)*iter;
9504 return (MonoClass *)item->data;
9511 * mono_class_is_delegate
9512 * @klass: the MonoClass to act on
9514 * Returns: TRUE if the MonoClass represents a System.Delegate.
9517 mono_class_is_delegate (MonoClass *klass)
9519 return klass->delegate;
9523 * mono_class_implements_interface
9524 * @klass: The MonoClass to act on
9525 * @interface: The interface to check if @klass implements.
9527 * Returns: TRUE if @klass implements @interface.
9530 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9532 return mono_class_is_assignable_from (iface, klass);
9536 * mono_field_get_name:
9537 * @field: the MonoClassField to act on
9539 * Returns: The name of the field.
9542 mono_field_get_name (MonoClassField *field)
9548 * mono_field_get_type:
9549 * @field: the MonoClassField to act on
9551 * Returns: MonoType of the field.
9554 mono_field_get_type (MonoClassField *field)
9557 MonoType *type = mono_field_get_type_checked (field, &error);
9558 if (!mono_error_ok (&error)) {
9559 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9560 mono_error_cleanup (&error);
9567 * mono_field_get_type_checked:
9568 * @field: the MonoClassField to act on
9569 * @error: used to return any erro found while retrieving @field type
9571 * Returns: MonoType of the field.
9574 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9576 mono_error_init (error);
9578 mono_field_resolve_type (field, error);
9583 * mono_field_get_parent:
9584 * @field: the MonoClassField to act on
9586 * Returns: MonoClass where the field was defined.
9589 mono_field_get_parent (MonoClassField *field)
9591 return field->parent;
9595 * mono_field_get_flags;
9596 * @field: the MonoClassField to act on
9598 * The metadata flags for a field are encoded using the
9599 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9601 * Returns: The flags for the field.
9604 mono_field_get_flags (MonoClassField *field)
9607 return mono_field_resolve_flags (field);
9608 return field->type->attrs;
9612 * mono_field_get_offset:
9613 * @field: the MonoClassField to act on
9615 * Returns: The field offset.
9618 mono_field_get_offset (MonoClassField *field)
9620 return field->offset;
9624 mono_field_get_rva (MonoClassField *field)
9628 MonoClass *klass = field->parent;
9629 MonoFieldDefaultValue *field_def_values;
9631 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9633 if (!klass->ext || !klass->ext->field_def_values) {
9634 mono_class_alloc_ext (klass);
9636 field_def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9638 mono_image_lock (klass->image);
9639 if (!klass->ext->field_def_values)
9640 klass->ext->field_def_values = field_def_values;
9641 mono_image_unlock (klass->image);
9644 field_index = mono_field_get_index (field);
9646 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9647 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9649 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9650 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9653 return klass->ext->field_def_values [field_index].data;
9657 * mono_field_get_data:
9658 * @field: the MonoClassField to act on
9660 * Returns: A pointer to the metadata constant value or to the field
9661 * data if it has an RVA flag.
9664 mono_field_get_data (MonoClassField *field)
9666 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9667 MonoTypeEnum def_type;
9669 return mono_class_get_field_default_value (field, &def_type);
9670 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9671 return mono_field_get_rva (field);
9678 * mono_property_get_name:
9679 * @prop: the MonoProperty to act on
9681 * Returns: The name of the property
9684 mono_property_get_name (MonoProperty *prop)
9690 * mono_property_get_set_method
9691 * @prop: the MonoProperty to act on.
9693 * Returns: The setter method of the property (A MonoMethod)
9696 mono_property_get_set_method (MonoProperty *prop)
9702 * mono_property_get_get_method
9703 * @prop: the MonoProperty to act on.
9705 * Returns: The setter method of the property (A MonoMethod)
9708 mono_property_get_get_method (MonoProperty *prop)
9714 * mono_property_get_parent:
9715 * @prop: the MonoProperty to act on.
9717 * Returns: The MonoClass where the property was defined.
9720 mono_property_get_parent (MonoProperty *prop)
9722 return prop->parent;
9726 * mono_property_get_flags:
9727 * @prop: the MonoProperty to act on.
9729 * The metadata flags for a property are encoded using the
9730 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9732 * Returns: The flags for the property.
9735 mono_property_get_flags (MonoProperty *prop)
9741 * mono_event_get_name:
9742 * @event: the MonoEvent to act on
9744 * Returns: The name of the event.
9747 mono_event_get_name (MonoEvent *event)
9753 * mono_event_get_add_method:
9754 * @event: The MonoEvent to act on.
9756 * Returns: The @add' method for the event (a MonoMethod).
9759 mono_event_get_add_method (MonoEvent *event)
9765 * mono_event_get_remove_method:
9766 * @event: The MonoEvent to act on.
9768 * Returns: The @remove method for the event (a MonoMethod).
9771 mono_event_get_remove_method (MonoEvent *event)
9773 return event->remove;
9777 * mono_event_get_raise_method:
9778 * @event: The MonoEvent to act on.
9780 * Returns: The @raise method for the event (a MonoMethod).
9783 mono_event_get_raise_method (MonoEvent *event)
9785 return event->raise;
9789 * mono_event_get_parent:
9790 * @event: the MonoEvent to act on.
9792 * Returns: The MonoClass where the event is defined.
9795 mono_event_get_parent (MonoEvent *event)
9797 return event->parent;
9801 * mono_event_get_flags
9802 * @event: the MonoEvent to act on.
9804 * The metadata flags for an event are encoded using the
9805 * EVENT_* constants. See the tabledefs.h file for details.
9807 * Returns: The flags for the event.
9810 mono_event_get_flags (MonoEvent *event)
9812 return event->attrs;
9816 * mono_class_get_method_from_name:
9817 * @klass: where to look for the method
9818 * @name: name of the method
9819 * @param_count: number of parameters. -1 for any number.
9821 * Obtains a MonoMethod with a given name and number of parameters.
9822 * It only works if there are no multiple signatures for any given method name.
9825 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9827 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9831 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9833 MonoMethod *res = NULL;
9836 /* Search directly in the metadata to avoid calling setup_methods () */
9837 for (i = 0; i < klass->method.count; ++i) {
9839 guint32 cols [MONO_METHOD_SIZE];
9841 MonoMethodSignature *sig;
9843 /* klass->method.first points into the methodptr table */
9844 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9846 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9847 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9849 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9852 if (param_count == -1) {
9856 sig = mono_method_signature_checked (method, &error);
9858 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9861 if (sig->param_count == param_count) {
9872 * mono_class_get_method_from_name_flags:
9873 * @klass: where to look for the method
9874 * @name_space: name of the method
9875 * @param_count: number of parameters. -1 for any number.
9876 * @flags: flags which must be set in the method
9878 * Obtains a MonoMethod with a given name and number of parameters.
9879 * It only works if there are no multiple signatures for any given method name.
9882 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9884 MonoMethod *res = NULL;
9887 mono_class_init (klass);
9889 if (klass->generic_class && !klass->methods) {
9890 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9893 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9894 if (!mono_error_ok (&error))
9895 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9900 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9901 mono_class_setup_methods (klass);
9903 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9904 See mono/tests/array_load_exception.il
9905 FIXME we should better report this error to the caller
9907 if (!klass->methods)
9909 for (i = 0; i < klass->method.count; ++i) {
9910 MonoMethod *method = klass->methods [i];
9912 if (method->name[0] == name [0] &&
9913 !strcmp (name, method->name) &&
9914 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9915 ((method->flags & flags) == flags)) {
9922 res = find_method_in_metadata (klass, name, param_count, flags);
9929 * mono_class_set_failure:
9930 * @klass: class in which the failure was detected
9931 * @ex_type: the kind of exception/error to be thrown (later)
9932 * @ex_data: exception data (specific to each type of exception/error)
9934 * Keep a detected failure informations in the class for later processing.
9935 * Note that only the first failure is kept.
9937 * LOCKING: Acquires the loader lock.
9940 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9942 if (mono_class_has_failure (klass))
9945 mono_loader_lock ();
9946 klass->exception_type = ex_type;
9948 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9949 mono_loader_unlock ();
9955 * mono_class_get_exception_data:
9957 * Return the exception_data property of KLASS.
9959 * LOCKING: Acquires the loader lock.
9962 mono_class_get_exception_data (MonoClass *klass)
9964 return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9968 * mono_classes_init:
9970 * Initialize the resources used by this module.
9973 mono_classes_init (void)
9975 mono_os_mutex_init (&classes_mutex);
9977 mono_counters_register ("Inflated methods size",
9978 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9979 mono_counters_register ("Inflated classes",
9980 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9981 mono_counters_register ("Inflated classes size",
9982 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9983 mono_counters_register ("MonoClass size",
9984 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9985 mono_counters_register ("MonoClassExt size",
9986 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
9990 * mono_classes_cleanup:
9992 * Free the resources used by this module.
9995 mono_classes_cleanup (void)
9997 if (global_interface_bitset)
9998 mono_bitset_free (global_interface_bitset);
9999 global_interface_bitset = NULL;
10000 mono_os_mutex_destroy (&classes_mutex);
10004 * mono_class_get_exception_for_failure:
10005 * @klass: class in which the failure was detected
10007 * Return a constructed MonoException than the caller can then throw
10008 * using mono_raise_exception - or NULL if no failure is present (or
10009 * doesn't result in an exception).
10012 mono_class_get_exception_for_failure (MonoClass *klass)
10014 gpointer exception_data = mono_class_get_exception_data (klass);
10016 switch (mono_class_get_failure(klass)) {
10017 case MONO_EXCEPTION_TYPE_LOAD: {
10020 char *str = mono_type_get_full_name (klass);
10021 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
10022 name = mono_string_new (mono_domain_get (), str);
10024 ex = mono_get_exception_type_load (name, astr);
10028 case MONO_EXCEPTION_MISSING_METHOD: {
10029 char *class_name = (char *)exception_data;
10030 char *assembly_name = class_name + strlen (class_name) + 1;
10032 return mono_get_exception_missing_method (class_name, assembly_name);
10034 case MONO_EXCEPTION_MISSING_FIELD: {
10035 char *class_name = (char *)exception_data;
10036 char *member_name = class_name + strlen (class_name) + 1;
10038 return mono_get_exception_missing_field (class_name, member_name);
10040 case MONO_EXCEPTION_FILE_NOT_FOUND: {
10041 char *msg_format = (char *)exception_data;
10042 char *assembly_name = msg_format + strlen (msg_format) + 1;
10043 char *msg = g_strdup_printf (msg_format, assembly_name);
10046 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
10052 case MONO_EXCEPTION_BAD_IMAGE: {
10053 return mono_get_exception_bad_image_format ((const char *)exception_data);
10055 case MONO_EXCEPTION_INVALID_PROGRAM: {
10056 return mono_exception_from_name_msg (mono_defaults.corlib, "System", "InvalidProgramException", "");
10059 /* TODO - handle other class related failures */
10060 return mono_get_exception_execution_engine ("Unknown class failure");
10066 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
10068 outer_klass = mono_class_get_generic_type_definition (outer_klass);
10069 inner_klass = mono_class_get_generic_type_definition (inner_klass);
10071 if (outer_klass == inner_klass)
10073 inner_klass = inner_klass->nested_in;
10074 } while (inner_klass);
10079 mono_class_get_generic_type_definition (MonoClass *klass)
10081 return klass->generic_class ? klass->generic_class->container_class : klass;
10085 * Check if @klass is a subtype of @parent ignoring generic instantiations.
10087 * Generic instantiations are ignored for all super types of @klass.
10089 * Visibility checks ignoring generic instantiations.
10092 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
10095 klass = mono_class_get_generic_type_definition (klass);
10096 parent = mono_class_get_generic_type_definition (parent);
10097 mono_class_setup_supertypes (klass);
10099 for (i = 0; i < klass->idepth; ++i) {
10100 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
10106 * Subtype can only access parent members with family protection if the site object
10107 * is subclass of Subtype. For example:
10108 * class A { protected int x; }
10110 * void valid_access () {
10114 * void invalid_access () {
10121 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
10123 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
10126 if (context_klass == NULL)
10128 /*if access_klass is not member_klass context_klass must be type compat*/
10129 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10135 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10138 if (accessing == accessed)
10140 if (!accessed || !accessing)
10143 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10144 * anywhere so untrusted friends are not safe to access platform's code internals */
10145 if (mono_security_core_clr_enabled ()) {
10146 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10150 mono_assembly_load_friends (accessed);
10151 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10152 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10153 /* Be conservative with checks */
10154 if (!friend_->name)
10156 if (strcmp (accessing->aname.name, friend_->name))
10158 if (friend_->public_key_token [0]) {
10159 if (!accessing->aname.public_key_token [0])
10161 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10170 * If klass is a generic type or if it is derived from a generic type, return the
10171 * MonoClass of the generic definition
10172 * Returns NULL if not found
10175 get_generic_definition_class (MonoClass *klass)
10178 if (klass->generic_class && klass->generic_class->container_class)
10179 return klass->generic_class->container_class;
10180 klass = klass->parent;
10186 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10189 for (i = 0; i < ginst->type_argc; ++i) {
10190 MonoType *type = ginst->type_argv[i];
10191 switch (type->type) {
10192 case MONO_TYPE_SZARRAY:
10193 if (!can_access_type (access_klass, type->data.klass))
10196 case MONO_TYPE_ARRAY:
10197 if (!can_access_type (access_klass, type->data.array->eklass))
10200 case MONO_TYPE_PTR:
10201 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10204 case MONO_TYPE_CLASS:
10205 case MONO_TYPE_VALUETYPE:
10206 case MONO_TYPE_GENERICINST:
10207 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10217 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10221 if (access_klass == member_klass)
10224 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10227 if (access_klass->element_class && !access_klass->enumtype)
10228 access_klass = access_klass->element_class;
10230 if (member_klass->element_class && !member_klass->enumtype)
10231 member_klass = member_klass->element_class;
10233 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10235 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10238 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
10241 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10244 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10247 /*Non nested type with nested visibility. We just fail it.*/
10248 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10251 switch (access_level) {
10252 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10253 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10255 case TYPE_ATTRIBUTE_PUBLIC:
10258 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10261 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10262 return is_nesting_type (member_klass, access_klass);
10264 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10265 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10267 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10268 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10270 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10271 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10272 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10274 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10275 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10276 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10281 /* FIXME: check visibility of type, too */
10283 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10285 MonoClass *member_generic_def;
10286 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10289 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
10290 access_klass->generic_container) &&
10291 (member_generic_def = get_generic_definition_class (member_klass))) {
10292 MonoClass *access_container;
10294 if (access_klass->generic_container)
10295 access_container = access_klass;
10297 access_container = access_klass->generic_class->container_class;
10299 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10303 /* Partition I 8.5.3.2 */
10304 /* the access level values are the same for fields and methods */
10305 switch (access_level) {
10306 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10307 /* same compilation unit */
10308 return access_klass->image == member_klass->image;
10309 case FIELD_ATTRIBUTE_PRIVATE:
10310 return access_klass == member_klass;
10311 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10312 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10313 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10316 case FIELD_ATTRIBUTE_ASSEMBLY:
10317 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10318 case FIELD_ATTRIBUTE_FAMILY:
10319 if (is_valid_family_access (access_klass, member_klass, context_klass))
10322 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10323 if (is_valid_family_access (access_klass, member_klass, context_klass))
10325 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10326 case FIELD_ATTRIBUTE_PUBLIC:
10333 * mono_method_can_access_field:
10334 * @method: Method that will attempt to access the field
10335 * @field: the field to access
10337 * Used to determine if a method is allowed to access the specified field.
10339 * Returns: TRUE if the given @method is allowed to access the @field while following
10340 * the accessibility rules of the CLI.
10343 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10345 /* FIXME: check all overlapping fields */
10346 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10348 MonoClass *nested = method->klass->nested_in;
10350 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10353 nested = nested->nested_in;
10360 * mono_method_can_access_method:
10361 * @method: Method that will attempt to access the other method
10362 * @called: the method that we want to probe for accessibility.
10364 * Used to determine if the @method is allowed to access the specified @called method.
10366 * Returns: TRUE if the given @method is allowed to invoke the @called while following
10367 * the accessibility rules of the CLI.
10370 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10372 method = mono_method_get_method_definition (method);
10373 called = mono_method_get_method_definition (called);
10374 return mono_method_can_access_method_full (method, called, NULL);
10378 * mono_method_can_access_method_full:
10379 * @method: The caller method
10380 * @called: The called method
10381 * @context_klass: The static type on stack of the owner @called object used
10383 * This function must be used with instance calls, as they have more strict family accessibility.
10384 * It can be used with static methods, but context_klass should be NULL.
10386 * Returns: TRUE if caller have proper visibility and acessibility to @called
10389 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10391 /* Wrappers are except from access checks */
10392 if (method->wrapper_type != MONO_WRAPPER_NONE || called->wrapper_type != MONO_WRAPPER_NONE)
10395 MonoClass *access_class = method->klass;
10396 MonoClass *member_class = called->klass;
10397 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10399 MonoClass *nested = access_class->nested_in;
10401 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10404 nested = nested->nested_in;
10411 can = can_access_type (access_class, member_class);
10413 MonoClass *nested = access_class->nested_in;
10415 can = can_access_type (nested, member_class);
10418 nested = nested->nested_in;
10425 if (called->is_inflated) {
10426 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10427 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10436 * mono_method_can_access_field_full:
10437 * @method: The caller method
10438 * @field: The accessed field
10439 * @context_klass: The static type on stack of the owner @field object used
10441 * This function must be used with instance fields, as they have more strict family accessibility.
10442 * It can be used with static fields, but context_klass should be NULL.
10444 * Returns: TRUE if caller have proper visibility and acessibility to @field
10447 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10449 MonoClass *access_class = method->klass;
10450 MonoClass *member_class = field->parent;
10451 /* FIXME: check all overlapping fields */
10452 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10454 MonoClass *nested = access_class->nested_in;
10456 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10459 nested = nested->nested_in;
10466 can = can_access_type (access_class, member_class);
10468 MonoClass *nested = access_class->nested_in;
10470 can = can_access_type (nested, member_class);
10473 nested = nested->nested_in;
10483 * mono_class_can_access_class:
10484 * @source_class: The source class
10485 * @target_class: The accessed class
10487 * This function returns is @target_class is visible to @source_class
10489 * Returns: TRUE if source have proper visibility and acessibility to target
10492 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10494 return can_access_type (source_class, target_class);
10498 * mono_type_is_valid_enum_basetype:
10499 * @type: The MonoType to check
10501 * Returns: TRUE if the type can be used as the basetype of an enum
10503 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10504 switch (type->type) {
10507 case MONO_TYPE_BOOLEAN:
10510 case MONO_TYPE_CHAR:
10524 * mono_class_is_valid_enum:
10525 * @klass: An enum class to be validated
10527 * This method verify the required properties an enum should have.
10529 * Returns: TRUE if the informed enum class is valid
10531 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10532 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10533 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10535 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10536 MonoClassField * field;
10537 gpointer iter = NULL;
10538 gboolean found_base_field = FALSE;
10540 g_assert (klass->enumtype);
10541 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10542 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10546 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10549 while ((field = mono_class_get_fields (klass, &iter))) {
10550 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10551 if (found_base_field)
10553 found_base_field = TRUE;
10554 if (!mono_type_is_valid_enum_basetype (field->type))
10559 if (!found_base_field)
10562 if (klass->method.count > 0)
10569 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10571 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10575 * mono_class_setup_interface_id:
10577 * Initializes MonoClass::interface_id if required.
10579 * LOCKING: Acquires the loader lock.
10582 mono_class_setup_interface_id (MonoClass *klass)
10584 mono_loader_lock ();
10585 if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10586 klass->interface_id = mono_get_unique_iid (klass);
10587 mono_loader_unlock ();
10591 * mono_class_alloc_ext:
10593 * Allocate klass->ext if not already done.
10596 mono_class_alloc_ext (MonoClass *klass)
10603 ext = (MonoClassExt *)mono_class_alloc0 (klass, sizeof (MonoClassExt));
10604 mono_image_lock (klass->image);
10605 mono_memory_barrier ();
10608 class_ext_size += sizeof (MonoClassExt);
10609 mono_image_unlock (klass->image);
10613 * mono_class_setup_interfaces:
10615 * Initialize klass->interfaces/interfaces_count.
10616 * LOCKING: Acquires the loader lock.
10617 * This function can fail the type.
10620 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10622 int i, interface_count;
10623 MonoClass **interfaces;
10625 mono_error_init (error);
10627 if (klass->interfaces_inited)
10630 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10631 MonoType *args [1];
10633 /* generic IList, ICollection, IEnumerable */
10634 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10635 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10637 args [0] = &klass->element_class->byval_arg;
10638 interfaces [0] = mono_class_bind_generic_parameters (
10639 mono_defaults.generic_ilist_class, 1, args, FALSE);
10640 if (interface_count > 1)
10641 interfaces [1] = mono_class_bind_generic_parameters (
10642 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10643 } else if (klass->generic_class) {
10644 MonoClass *gklass = klass->generic_class->container_class;
10646 mono_class_setup_interfaces (gklass, error);
10647 if (!mono_error_ok (error)) {
10648 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10652 interface_count = gklass->interface_count;
10653 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10654 for (i = 0; i < interface_count; i++) {
10655 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10656 if (!mono_error_ok (error)) {
10657 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10662 interface_count = 0;
10666 mono_image_lock (klass->image);
10668 if (!klass->interfaces_inited) {
10669 klass->interface_count = interface_count;
10670 klass->interfaces = interfaces;
10672 mono_memory_barrier ();
10674 klass->interfaces_inited = TRUE;
10677 mono_image_unlock (klass->image);
10681 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10683 MonoClass *klass = field->parent;
10684 MonoImage *image = klass->image;
10685 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10686 int field_idx = field - klass->fields;
10688 mono_error_init (error);
10691 MonoClassField *gfield = >d->fields [field_idx];
10692 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10693 if (!mono_error_ok (error)) {
10694 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10695 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10698 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10699 if (!mono_error_ok (error)) {
10700 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10701 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10705 guint32 cols [MONO_FIELD_SIZE];
10706 MonoGenericContainer *container = NULL;
10707 int idx = klass->field.first + field_idx;
10709 /*FIXME, in theory we do not lazy load SRE fields*/
10710 g_assert (!image_is_dynamic (image));
10712 if (klass->generic_container) {
10713 container = klass->generic_container;
10715 container = gtd->generic_container;
10716 g_assert (container);
10719 /* klass->field.first and idx points into the fieldptr table */
10720 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10722 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10723 mono_error_set_type_load_class (error, klass, "Could not verify field %s signature", field->name);;
10724 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
10728 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10730 mono_metadata_decode_value (sig, &sig);
10731 /* FIELD signature == 0x06 */
10732 g_assert (*sig == 0x06);
10734 field->type = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10735 if (!field->type) {
10736 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10737 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10743 mono_field_resolve_flags (MonoClassField *field)
10745 MonoClass *klass = field->parent;
10746 MonoImage *image = klass->image;
10747 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10748 int field_idx = field - klass->fields;
10752 MonoClassField *gfield = >d->fields [field_idx];
10753 return mono_field_get_flags (gfield);
10755 int idx = klass->field.first + field_idx;
10757 /*FIXME, in theory we do not lazy load SRE fields*/
10758 g_assert (!image_is_dynamic (image));
10760 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10765 * mono_class_setup_basic_field_info:
10766 * @class: The class to initialize
10768 * Initializes the klass->fields array of fields.
10769 * Aquires the loader lock.
10772 mono_class_setup_basic_field_info_locking (MonoClass *klass)
10774 mono_loader_lock ();
10775 mono_class_setup_basic_field_info (klass);
10776 mono_loader_unlock ();
10780 * mono_class_get_fields_lazy:
10781 * @klass: the MonoClass to act on
10783 * This routine is an iterator routine for retrieving the fields in a class.
10784 * Only minimal information about fields are loaded. Accessors must be used
10785 * for all MonoClassField returned.
10787 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10788 * iterate over all of the elements. When no more values are
10789 * available, the return value is NULL.
10791 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10794 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10796 MonoClassField* field;
10800 mono_class_setup_basic_field_info_locking (klass);
10801 if (!klass->fields)
10803 /* start from the first */
10804 if (klass->field.count) {
10805 *iter = &klass->fields [0];
10806 return (MonoClassField *)*iter;
10812 field = (MonoClassField *)*iter;
10814 if (field < &klass->fields [klass->field.count]) {
10816 return (MonoClassField *)*iter;
10822 mono_class_full_name (MonoClass *klass)
10824 return mono_type_full_name (&klass->byval_arg);
10827 /* Declare all shared lazy type lookup functions */
10828 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, System.Runtime.InteropServices, SafeHandle)