2 * class.c: Class management for the Mono runtime
5 * Miguel de Icaza (miguel@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9 * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
10 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
20 #include <mono/metadata/image.h>
21 #include <mono/metadata/assembly.h>
22 #include <mono/metadata/metadata.h>
23 #include <mono/metadata/metadata-internals.h>
24 #include <mono/metadata/profiler-private.h>
25 #include <mono/metadata/tabledefs.h>
26 #include <mono/metadata/tokentype.h>
27 #include <mono/metadata/class-internals.h>
28 #include <mono/metadata/object.h>
29 #include <mono/metadata/appdomain.h>
30 #include <mono/metadata/mono-endian.h>
31 #include <mono/metadata/debug-helpers.h>
32 #include <mono/metadata/reflection.h>
33 #include <mono/metadata/exception.h>
34 #include <mono/metadata/security-manager.h>
35 #include <mono/metadata/security-core-clr.h>
36 #include <mono/metadata/attrdefs.h>
37 #include <mono/metadata/gc-internals.h>
38 #include <mono/metadata/verify-internals.h>
39 #include <mono/metadata/mono-debug.h>
40 #include <mono/utils/mono-counters.h>
41 #include <mono/utils/mono-string.h>
42 #include <mono/utils/mono-error-internals.h>
43 #include <mono/utils/mono-logger-internals.h>
44 #include <mono/utils/mono-memory-model.h>
45 #include <mono/utils/atomic.h>
46 #include <mono/utils/bsearch.h>
47 #include <mono/utils/checked-build.h>
51 gboolean mono_print_vtable = FALSE;
52 gboolean mono_align_small_structs = FALSE;
55 guint32 inflated_classes, inflated_classes_size, inflated_methods_size;
56 guint32 classes_size, class_ext_size;
58 /* Low level lock which protects data structures in this module */
59 static mono_mutex_t classes_mutex;
61 /* Function supplied by the runtime to find classes by name using information from the AOT file */
62 static MonoGetClassFromName get_class_from_name = NULL;
64 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error);
65 static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
66 static gboolean can_access_type (MonoClass *access_klass, MonoClass *member_klass);
67 static MonoMethod* find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags);
68 static int generic_array_methods (MonoClass *klass);
69 static void setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos);
71 static MonoMethod* mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter);
72 static char* mono_assembly_name_from_token (MonoImage *image, guint32 type_token);
73 static void mono_field_resolve_type (MonoClassField *field, MonoError *error);
74 static guint32 mono_field_resolve_flags (MonoClassField *field);
75 static void mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup);
76 static void mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gklass);
79 We use gclass recording to allow recursive system f types to be referenced by a parent.
81 Given the following type hierarchy:
83 class TextBox : TextBoxBase<TextBox> {}
84 class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
85 class TextInput<T> : Input<T> where T: TextInput<T> {}
88 The runtime tries to load TextBoxBase<>.
89 To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
90 To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
91 To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
93 At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded
94 at this point, iow, both are registered in the type map and both and a NULL parent. This means
95 that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
97 To fix that what we do is to record all generic instantes created while resolving the parent of
98 any generic type definition and, after resolved, correct the parent field if needed.
101 static int record_gclass_instantiation;
102 static GSList *gclass_recorded_list;
103 typedef gboolean (*gclass_record_func) (MonoClass*, void*);
108 mono_locks_os_acquire (&classes_mutex, ClassesLock);
112 classes_unlock (void)
114 mono_locks_os_release (&classes_mutex, ClassesLock);
118 * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
121 enable_gclass_recording (void)
123 ++record_gclass_instantiation;
127 * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
130 disable_gclass_recording (gclass_record_func func, void *user_data)
132 GSList **head = &gclass_recorded_list;
134 g_assert (record_gclass_instantiation > 0);
135 --record_gclass_instantiation;
138 GSList *node = *head;
139 if (func ((MonoClass*)node->data, user_data)) {
141 g_slist_free_1 (node);
147 /* We automatically discard all recorded gclasses when disabled. */
148 if (!record_gclass_instantiation && gclass_recorded_list) {
149 g_slist_free (gclass_recorded_list);
150 gclass_recorded_list = NULL;
155 * mono_class_from_typeref:
156 * @image: a MonoImage
157 * @type_token: a TypeRef token
159 * Creates the MonoClass* structure representing the type defined by
160 * the typeref token valid inside @image.
161 * Returns: The MonoClass* representing the typeref token, NULL ifcould
165 mono_class_from_typeref (MonoImage *image, guint32 type_token)
168 MonoClass *klass = mono_class_from_typeref_checked (image, type_token, &error);
169 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
174 * mono_class_from_typeref_checked:
175 * @image: a MonoImage
176 * @type_token: a TypeRef token
177 * @error: error return code, if any.
179 * Creates the MonoClass* structure representing the type defined by
180 * the typeref token valid inside @image.
182 * Returns: The MonoClass* representing the typeref token, NULL if it could
183 * not be loaded with the @error value filled with the information about the
187 mono_class_from_typeref_checked (MonoImage *image, guint32 type_token, MonoError *error)
189 guint32 cols [MONO_TYPEREF_SIZE];
190 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
192 const char *name, *nspace;
193 MonoClass *res = NULL;
196 mono_error_init (error);
198 if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, error))
201 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
203 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
204 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
206 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
207 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
208 case MONO_RESOLUTION_SCOPE_MODULE:
210 LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
211 This is not the observed behavior of existing implementations.
212 The defacto behavior is that it's just a typedef in disguise.
214 /* a typedef in disguise */
215 res = mono_class_from_name_checked (image, nspace, name, error);
218 case MONO_RESOLUTION_SCOPE_MODULEREF:
219 module = mono_image_load_module (image, idx);
221 res = mono_class_from_name_checked (module, nspace, name, error);
224 case MONO_RESOLUTION_SCOPE_TYPEREF: {
225 MonoClass *enclosing;
228 if (idx == mono_metadata_token_index (type_token)) {
229 mono_error_set_bad_image (error, image, "Image with self-referencing typeref token %08x.", type_token);
233 enclosing = mono_class_from_typeref_checked (image, MONO_TOKEN_TYPE_REF | idx, error);
234 return_val_if_nok (error, NULL);
236 if (enclosing->nested_classes_inited && enclosing->ext) {
237 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
238 for (tmp = enclosing->ext->nested_classes; tmp; tmp = tmp->next) {
239 res = (MonoClass *)tmp->data;
240 if (strcmp (res->name, name) == 0)
244 /* Don't call mono_class_init as we might've been called by it recursively */
245 int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
247 guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
248 guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
249 const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
251 if (strcmp (nname, name) == 0)
252 return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, error);
254 i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
257 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name);
260 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
264 if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) {
265 mono_error_set_bad_image (error, image, "Image with invalid assemblyref token %08x.", idx);
269 if (!image->references || !image->references [idx - 1])
270 mono_assembly_load_reference (image, idx - 1);
271 g_assert (image->references [idx - 1]);
273 /* If the assembly did not load, register this as a type load exception */
274 if (image->references [idx - 1] == REFERENCE_MISSING){
275 MonoAssemblyName aname;
278 mono_assembly_get_assemblyref (image, idx - 1, &aname);
279 human_name = mono_stringify_assembly_name (&aname);
280 mono_error_set_assembly_load_simple (error, human_name, image->assembly ? image->assembly->ref_only : FALSE);
284 res = mono_class_from_name_checked (image->references [idx - 1]->image, nspace, name, error);
287 /* Generic case, should be avoided for when a better error is possible. */
288 if (!res && mono_error_ok (error)) {
289 char *name = mono_class_name_from_token (image, type_token);
290 char *assembly = mono_assembly_name_from_token (image, type_token);
291 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
298 mono_image_memdup (MonoImage *image, void *data, guint size)
300 void *res = mono_image_alloc (image, size);
301 memcpy (res, data, size);
305 /* Copy everything mono_metadata_free_array free. */
307 mono_dup_array_type (MonoImage *image, MonoArrayType *a)
310 a = (MonoArrayType *)mono_image_memdup (image, a, sizeof (MonoArrayType));
312 a->sizes = (int *)mono_image_memdup (image, a->sizes, a->numsizes * sizeof (int));
314 a->lobounds = (int *)mono_image_memdup (image, a->lobounds, a->numlobounds * sizeof (int));
316 a = (MonoArrayType *)g_memdup (a, sizeof (MonoArrayType));
318 a->sizes = (int *)g_memdup (a->sizes, a->numsizes * sizeof (int));
320 a->lobounds = (int *)g_memdup (a->lobounds, a->numlobounds * sizeof (int));
325 /* Copy everything mono_metadata_free_method_signature free. */
327 mono_metadata_signature_deep_dup (MonoImage *image, MonoMethodSignature *sig)
331 sig = mono_metadata_signature_dup_full (image, sig);
333 sig->ret = mono_metadata_type_dup (image, sig->ret);
334 for (i = 0; i < sig->param_count; ++i)
335 sig->params [i] = mono_metadata_type_dup (image, sig->params [i]);
341 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
343 MonoAssembly *ta = klass->image->assembly;
346 name = mono_stringify_assembly_name (&ta->aname);
347 g_string_append_printf (str, ", %s", name);
352 mono_type_name_check_byref (MonoType *type, GString *str)
355 g_string_append_c (str, '&');
359 * mono_identifier_escape_type_name_chars:
360 * @str: a destination string
361 * @identifier: an IDENTIFIER in internal form
365 * The displayed form of the identifier is appended to str.
367 * The displayed form of an identifier has the characters ,+&*[]\
368 * that have special meaning in type names escaped with a preceeding
369 * backslash (\) character.
372 mono_identifier_escape_type_name_chars (GString* str, const char* identifier)
378 // reserve space for common case: there will be no escaped characters.
379 g_string_set_size(str, n + strlen(identifier));
380 g_string_set_size(str, n);
382 for (const char* s = identifier; *s != 0 ; s++) {
391 g_string_append_c (str, '\\');
392 g_string_append_c (str, *s);
395 g_string_append_c (str, *s);
403 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
404 MonoTypeNameFormat format)
408 switch (type->type) {
409 case MONO_TYPE_ARRAY: {
410 int i, rank = type->data.array->rank;
411 MonoTypeNameFormat nested_format;
413 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
414 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
416 mono_type_get_name_recurse (
417 &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
418 g_string_append_c (str, '[');
420 g_string_append_c (str, '*');
421 for (i = 1; i < rank; i++)
422 g_string_append_c (str, ',');
423 g_string_append_c (str, ']');
425 mono_type_name_check_byref (type, str);
427 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
428 _mono_type_get_assembly_name (type->data.array->eklass, str);
431 case MONO_TYPE_SZARRAY: {
432 MonoTypeNameFormat nested_format;
434 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
435 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
437 mono_type_get_name_recurse (
438 &type->data.klass->byval_arg, str, FALSE, nested_format);
439 g_string_append (str, "[]");
441 mono_type_name_check_byref (type, str);
443 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
444 _mono_type_get_assembly_name (type->data.klass, str);
447 case MONO_TYPE_PTR: {
448 MonoTypeNameFormat nested_format;
450 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
451 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
453 mono_type_get_name_recurse (
454 type->data.type, str, FALSE, nested_format);
455 g_string_append_c (str, '*');
457 mono_type_name_check_byref (type, str);
459 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
460 _mono_type_get_assembly_name (mono_class_from_mono_type (type->data.type), str);
465 if (!mono_generic_param_info (type->data.generic_param))
466 g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num);
468 g_string_append (str, mono_generic_param_info (type->data.generic_param)->name);
470 mono_type_name_check_byref (type, str);
474 klass = mono_class_from_mono_type (type);
475 if (klass->nested_in) {
476 mono_type_get_name_recurse (
477 &klass->nested_in->byval_arg, str, TRUE, format);
478 if (format == MONO_TYPE_NAME_FORMAT_IL)
479 g_string_append_c (str, '.');
481 g_string_append_c (str, '+');
482 } else if (*klass->name_space) {
483 if (format == MONO_TYPE_NAME_FORMAT_IL)
484 g_string_append (str, klass->name_space);
486 mono_identifier_escape_type_name_chars (str, klass->name_space);
487 g_string_append_c (str, '.');
489 if (format == MONO_TYPE_NAME_FORMAT_IL) {
490 char *s = strchr (klass->name, '`');
491 int len = s ? s - klass->name : strlen (klass->name);
492 g_string_append_len (str, klass->name, len);
494 mono_identifier_escape_type_name_chars (str, klass->name);
498 if (klass->generic_class) {
499 MonoGenericClass *gclass = klass->generic_class;
500 MonoGenericInst *inst = gclass->context.class_inst;
501 MonoTypeNameFormat nested_format;
504 nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
505 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
507 if (format == MONO_TYPE_NAME_FORMAT_IL)
508 g_string_append_c (str, '<');
510 g_string_append_c (str, '[');
511 for (i = 0; i < inst->type_argc; i++) {
512 MonoType *t = inst->type_argv [i];
515 g_string_append_c (str, ',');
516 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
517 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
518 g_string_append_c (str, '[');
519 mono_type_get_name_recurse (inst->type_argv [i], str, FALSE, nested_format);
520 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
521 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
522 g_string_append_c (str, ']');
524 if (format == MONO_TYPE_NAME_FORMAT_IL)
525 g_string_append_c (str, '>');
527 g_string_append_c (str, ']');
528 } else if (klass->generic_container &&
529 (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
530 (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
533 if (format == MONO_TYPE_NAME_FORMAT_IL)
534 g_string_append_c (str, '<');
536 g_string_append_c (str, '[');
537 for (i = 0; i < klass->generic_container->type_argc; i++) {
539 g_string_append_c (str, ',');
540 g_string_append (str, mono_generic_container_get_param_info (klass->generic_container, i)->name);
542 if (format == MONO_TYPE_NAME_FORMAT_IL)
543 g_string_append_c (str, '>');
545 g_string_append_c (str, ']');
548 mono_type_name_check_byref (type, str);
550 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
551 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
552 _mono_type_get_assembly_name (klass, str);
558 * mono_type_get_name_full:
560 * @format: the format for the return string.
563 * Returns: The string representation in a number of formats:
565 * if format is MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
566 * returned in the formatrequired by System.Reflection, this is the
567 * inverse of mono_reflection_parse_type ().
569 * if format is MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
570 * be used by the IL assembler.
572 * if format is MONO_TYPE_NAME_FORMAT_FULL_NAME
574 * if format is MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
577 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
581 result = g_string_new ("");
583 mono_type_get_name_recurse (type, result, FALSE, format);
585 return g_string_free (result, FALSE);
589 * mono_type_get_full_name:
592 * Returns: The string representation for type as required by System.Reflection.
593 * The inverse of mono_reflection_parse_type ().
596 mono_type_get_full_name (MonoClass *klass)
598 return mono_type_get_name_full (mono_class_get_type (klass), MONO_TYPE_NAME_FORMAT_REFLECTION);
602 * mono_type_get_name:
605 * Returns: The string representation for type as it would be represented in IL code.
608 mono_type_get_name (MonoType *type)
610 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
614 * mono_type_get_underlying_type:
617 * Returns: The MonoType for the underlying integer type if @type
618 * is an enum and byref is false, otherwise the type itself.
621 mono_type_get_underlying_type (MonoType *type)
623 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype && !type->byref)
624 return mono_class_enum_basetype (type->data.klass);
625 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype && !type->byref)
626 return mono_class_enum_basetype (type->data.generic_class->container_class);
631 * mono_class_is_open_constructed_type:
634 * Returns: TRUE if type represents a generics open constructed type.
635 * IOW, not all type parameters required for the instantiation have
636 * been provided or it's a generic type definition.
638 * An open constructed type means it's a non realizable type. Not to
639 * be mixed up with an abstract type - we can't cast or dispatch to
640 * an open type, for example.
643 mono_class_is_open_constructed_type (MonoType *t)
649 case MONO_TYPE_SZARRAY:
650 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
651 case MONO_TYPE_ARRAY:
652 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
654 return mono_class_is_open_constructed_type (t->data.type);
655 case MONO_TYPE_GENERICINST:
656 return t->data.generic_class->context.class_inst->is_open;
657 case MONO_TYPE_CLASS:
658 case MONO_TYPE_VALUETYPE:
659 return t->data.klass->generic_container != NULL;
666 This is a simple function to catch the most common bad instances of generic types.
667 Specially those that might lead to further failures in the runtime.
670 is_valid_generic_argument (MonoType *type)
672 switch (type->type) {
674 //case MONO_TYPE_TYPEDBYREF:
682 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
684 mono_error_init (error);
686 switch (type->type) {
687 case MONO_TYPE_MVAR: {
689 int num = mono_type_get_generic_param_num (type);
690 MonoGenericInst *inst = context->method_inst;
693 if (num >= inst->type_argc) {
694 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
695 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
696 num, info ? info->name : "", inst->type_argc);
700 if (!is_valid_generic_argument (inst->type_argv [num])) {
701 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
702 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
703 num, info ? info->name : "", inst->type_argv [num]->type);
707 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
708 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
709 * ->byref and ->attrs from @type are propagated to the returned type.
711 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
712 nt->byref = type->byref;
713 nt->attrs = type->attrs;
716 case MONO_TYPE_VAR: {
718 int num = mono_type_get_generic_param_num (type);
719 MonoGenericInst *inst = context->class_inst;
722 if (num >= inst->type_argc) {
723 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
724 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
725 num, info ? info->name : "", inst->type_argc);
728 if (!is_valid_generic_argument (inst->type_argv [num])) {
729 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
730 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
731 num, info ? info->name : "", inst->type_argv [num]->type);
734 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
735 nt->byref = type->byref;
736 nt->attrs = type->attrs;
739 case MONO_TYPE_SZARRAY: {
740 MonoClass *eclass = type->data.klass;
741 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
742 if (!inflated || !mono_error_ok (error))
744 nt = mono_metadata_type_dup (image, type);
745 nt->data.klass = mono_class_from_mono_type (inflated);
746 mono_metadata_free_type (inflated);
749 case MONO_TYPE_ARRAY: {
750 MonoClass *eclass = type->data.array->eklass;
751 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
752 if (!inflated || !mono_error_ok (error))
754 nt = mono_metadata_type_dup (image, type);
755 nt->data.array->eklass = mono_class_from_mono_type (inflated);
756 mono_metadata_free_type (inflated);
759 case MONO_TYPE_GENERICINST: {
760 MonoGenericClass *gclass = type->data.generic_class;
761 MonoGenericInst *inst;
763 if (!gclass->context.class_inst->is_open)
766 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
767 return_val_if_nok (error, NULL);
769 if (inst != gclass->context.class_inst)
770 gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
772 if (gclass == type->data.generic_class)
775 nt = mono_metadata_type_dup (image, type);
776 nt->data.generic_class = gclass;
779 case MONO_TYPE_CLASS:
780 case MONO_TYPE_VALUETYPE: {
781 MonoClass *klass = type->data.klass;
782 MonoGenericContainer *container = klass->generic_container;
783 MonoGenericInst *inst;
784 MonoGenericClass *gclass = NULL;
790 /* We can't use context->class_inst directly, since it can have more elements */
791 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
792 return_val_if_nok (error, NULL);
794 if (inst == container->context.class_inst)
797 gclass = mono_metadata_lookup_generic_class (klass, inst, image_is_dynamic (klass->image));
799 nt = mono_metadata_type_dup (image, type);
800 nt->type = MONO_TYPE_GENERICINST;
801 nt->data.generic_class = gclass;
811 mono_generic_class_get_context (MonoGenericClass *gclass)
813 return &gclass->context;
817 mono_class_get_context (MonoClass *klass)
819 return klass->generic_class ? mono_generic_class_get_context (klass->generic_class) : NULL;
823 * mono_class_get_generic_container:
825 * Return the generic container of KLASS which should be a generic type definition.
827 MonoGenericContainer*
828 mono_class_get_generic_container (MonoClass *klass)
830 g_assert (klass->is_generic);
832 return klass->generic_container;
836 * mono_class_get_generic_class:
838 * Return the MonoGenericClass of KLASS, which should be a generic instance.
841 mono_class_get_generic_class (MonoClass *klass)
843 g_assert (klass->is_inflated);
845 return klass->generic_class;
849 * mono_class_inflate_generic_type_with_mempool:
850 * @mempool: a mempool
852 * @context: a generics context
853 * @error: error context
855 * The same as mono_class_inflate_generic_type, but allocates the MonoType
856 * from mempool if it is non-NULL. If it is NULL, the MonoType is
857 * allocated on the heap and is owned by the caller.
858 * The returned type can potentially be the same as TYPE, so it should not be
859 * modified by the caller, and it should be freed using mono_metadata_free_type ().
862 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
864 MonoType *inflated = NULL;
865 mono_error_init (error);
868 inflated = inflate_generic_type (image, type, context, error);
869 return_val_if_nok (error, NULL);
872 MonoType *shared = mono_metadata_get_shared_type (type);
877 return mono_metadata_type_dup (image, type);
881 mono_stats.inflated_type_count++;
886 * mono_class_inflate_generic_type:
888 * @context: a generics context
890 * If @type is a generic type and @context is not NULL, instantiate it using the
891 * generics context @context.
893 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
894 * on the heap and is owned by the caller. Returns NULL on error.
896 * @deprecated Please use mono_class_inflate_generic_type_checked instead
899 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
903 result = mono_class_inflate_generic_type_checked (type, context, &error);
904 mono_error_cleanup (&error);
909 * mono_class_inflate_generic_type:
911 * @context: a generics context
912 * @error: error context to use
914 * If @type is a generic type and @context is not NULL, instantiate it using the
915 * generics context @context.
917 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
918 * on the heap and is owned by the caller.
921 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
923 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
927 * mono_class_inflate_generic_type_no_copy:
929 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
933 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
935 MonoType *inflated = NULL;
937 mono_error_init (error);
939 inflated = inflate_generic_type (image, type, context, error);
940 return_val_if_nok (error, NULL);
946 mono_stats.inflated_type_count++;
951 * mono_class_inflate_generic_class:
953 * Inflate the class @gklass with @context. Set @error on failure.
956 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
961 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
962 return_val_if_nok (error, NULL);
964 res = mono_class_from_mono_type (inflated);
965 mono_metadata_free_type (inflated);
970 static MonoGenericContext
971 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
973 MonoGenericInst *class_inst = NULL;
974 MonoGenericInst *method_inst = NULL;
975 MonoGenericContext res = { NULL, NULL };
977 mono_error_init (error);
979 if (context->class_inst) {
980 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
981 if (!mono_error_ok (error))
985 if (context->method_inst) {
986 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
987 if (!mono_error_ok (error))
991 res.class_inst = class_inst;
992 res.method_inst = method_inst;
998 * mono_class_inflate_generic_method:
999 * @method: a generic method
1000 * @context: a generics context
1002 * Instantiate the generic method @method using the generics context @context.
1004 * Returns: The new instantiated method
1007 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
1009 return mono_class_inflate_generic_method_full (method, NULL, context);
1013 mono_class_inflate_generic_method_checked (MonoMethod *method, MonoGenericContext *context, MonoError *error)
1015 return mono_class_inflate_generic_method_full_checked (method, NULL, context, error);
1019 * mono_class_inflate_generic_method_full:
1021 * Instantiate method @method with the generic context @context.
1022 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
1023 * Use mono_method_signature () and mono_method_get_header () to get the correct values.
1026 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
1029 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
1030 if (!mono_error_ok (&error))
1031 /*FIXME do proper error handling - on this case, kill this function. */
1032 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
1038 * mono_class_inflate_generic_method_full_checked:
1039 * Same as mono_class_inflate_generic_method_full but return failure using @error.
1042 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
1045 MonoMethodInflated *iresult, *cached;
1046 MonoMethodSignature *sig;
1047 MonoGenericContext tmp_context;
1049 mono_error_init (error);
1051 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1052 while (method->is_inflated) {
1053 MonoGenericContext *method_context = mono_method_get_context (method);
1054 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1056 tmp_context = inflate_generic_context (method_context, context, error);
1057 return_val_if_nok (error, NULL);
1059 context = &tmp_context;
1061 if (mono_metadata_generic_context_equal (method_context, context))
1064 method = imethod->declaring;
1068 * A method only needs to be inflated if the context has argument for which it is
1071 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1072 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1075 if (!((method->is_generic && context->method_inst) ||
1076 (method->klass->generic_container && context->class_inst)))
1079 iresult = g_new0 (MonoMethodInflated, 1);
1080 iresult->context = *context;
1081 iresult->declaring = method;
1083 if (!context->method_inst && method->is_generic)
1084 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1086 if (!context->class_inst) {
1087 g_assert (!iresult->declaring->klass->generic_class);
1088 if (iresult->declaring->klass->generic_container)
1089 iresult->context.class_inst = iresult->declaring->klass->generic_container->context.class_inst;
1090 else if (iresult->declaring->klass->generic_class)
1091 iresult->context.class_inst = iresult->declaring->klass->generic_class->context.class_inst;
1093 /* This can happen with some callers like mono_object_get_virtual_method () */
1094 if (!iresult->declaring->klass->generic_container && !iresult->declaring->klass->generic_class)
1095 iresult->context.class_inst = NULL;
1097 MonoImageSet *set = mono_metadata_get_image_set_for_method (iresult);
1100 mono_image_set_lock (set);
1101 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1102 mono_image_set_unlock (set);
1106 return (MonoMethod*)cached;
1109 mono_stats.inflated_method_count++;
1111 inflated_methods_size += sizeof (MonoMethodInflated);
1113 sig = mono_method_signature (method);
1115 char *name = mono_type_get_full_name (method->klass);
1116 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1122 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1124 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1127 result = (MonoMethod *) iresult;
1128 result->is_inflated = TRUE;
1129 result->is_generic = FALSE;
1130 result->sre_method = FALSE;
1131 result->signature = NULL;
1133 if (iresult->context.method_inst) {
1134 /* Set the generic_container of the result to the generic_container of method */
1135 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1137 if (generic_container && iresult->context.method_inst == generic_container->context.method_inst) {
1138 result->is_generic = 1;
1139 mono_method_set_generic_container (result, generic_container);
1143 if (!klass_hint || !klass_hint->generic_class ||
1144 klass_hint->generic_class->container_class != method->klass ||
1145 klass_hint->generic_class->context.class_inst != context->class_inst)
1148 if (method->klass->generic_container)
1149 result->klass = klass_hint;
1151 if (!result->klass) {
1152 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1153 if (!mono_error_ok (error))
1156 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1158 mono_metadata_free_type (inflated);
1162 * FIXME: This should hold, but it doesn't:
1164 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1165 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1166 * g_assert (result->is_generic);
1169 * Fixing this here causes other things to break, hence a very
1170 * ugly hack in mini-trampolines.c - see
1171 * is_generic_method_definition().
1175 mono_image_set_lock (set);
1176 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1178 g_hash_table_insert (set->gmethod_cache, iresult, iresult);
1179 iresult->owner = set;
1182 mono_image_set_unlock (set);
1184 return (MonoMethod*)cached;
1192 * mono_get_inflated_method:
1194 * Obsolete. We keep it around since it's mentioned in the public API.
1197 mono_get_inflated_method (MonoMethod *method)
1203 * mono_method_get_context_general:
1205 * @uninflated: handle uninflated methods?
1207 * Returns the generic context of a method or NULL if it doesn't have
1208 * one. For an inflated method that's the context stored in the
1209 * method. Otherwise it's in the method's generic container or in the
1210 * generic container of the method's class.
1213 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1215 if (method->is_inflated) {
1216 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1217 return &imethod->context;
1221 if (method->is_generic)
1222 return &(mono_method_get_generic_container (method)->context);
1223 if (method->klass->generic_container)
1224 return &method->klass->generic_container->context;
1229 * mono_method_get_context:
1232 * Returns the generic context for method if it's inflated, otherwise
1236 mono_method_get_context (MonoMethod *method)
1238 return mono_method_get_context_general (method, FALSE);
1242 * mono_method_get_generic_container:
1244 * Returns the generic container of METHOD, which should be a generic method definition.
1245 * Returns NULL if METHOD is not a generic method definition.
1246 * LOCKING: Acquires the loader lock.
1248 MonoGenericContainer*
1249 mono_method_get_generic_container (MonoMethod *method)
1251 MonoGenericContainer *container;
1253 if (!method->is_generic)
1256 container = (MonoGenericContainer *)mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1257 g_assert (container);
1263 * mono_method_set_generic_container:
1265 * Sets the generic container of METHOD to CONTAINER.
1266 * LOCKING: Acquires the image lock.
1269 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1271 g_assert (method->is_generic);
1273 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1277 * mono_class_find_enum_basetype:
1278 * @class: The enum class
1280 * Determine the basetype of an enum by iterating through its fields. We do this
1281 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1284 mono_class_find_enum_basetype (MonoClass *klass, MonoError *error)
1286 MonoGenericContainer *container = NULL;
1287 MonoImage *m = klass->image;
1288 const int top = klass->field.count;
1291 g_assert (klass->enumtype);
1293 mono_error_init (error);
1295 if (klass->generic_container)
1296 container = klass->generic_container;
1297 else if (klass->generic_class) {
1298 MonoClass *gklass = klass->generic_class->container_class;
1300 container = gklass->generic_container;
1301 g_assert (container);
1305 * Fetch all the field information.
1307 for (i = 0; i < top; i++){
1309 guint32 cols [MONO_FIELD_SIZE];
1310 int idx = klass->field.first + i;
1313 /* klass->field.first and idx points into the fieldptr table */
1314 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1316 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1319 if (!mono_verifier_verify_field_signature (klass->image, cols [MONO_FIELD_SIGNATURE], NULL)) {
1320 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x", cols [MONO_FIELD_SIGNATURE]);
1324 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1325 mono_metadata_decode_value (sig, &sig);
1326 /* FIELD signature == 0x06 */
1328 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig);
1332 ftype = mono_metadata_parse_type_checked (m, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
1336 if (klass->generic_class) {
1337 //FIXME do we leak here?
1338 ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (klass), error);
1339 if (!mono_error_ok (error))
1341 ftype->attrs = cols [MONO_FIELD_FLAGS];
1346 mono_error_set_type_load_class (error, klass, "Could not find base type");
1353 * Checks for MonoClass::exception_type without resolving all MonoType's into MonoClass'es
1356 mono_type_has_exceptions (MonoType *type)
1358 switch (type->type) {
1359 case MONO_TYPE_CLASS:
1360 case MONO_TYPE_VALUETYPE:
1361 case MONO_TYPE_SZARRAY:
1362 return mono_class_has_failure (type->data.klass);
1363 case MONO_TYPE_ARRAY:
1364 return mono_class_has_failure (type->data.array->eklass);
1365 case MONO_TYPE_GENERICINST:
1366 return mono_class_has_failure (mono_generic_class_get_class (type->data.generic_class));
1373 mono_error_set_for_class_failure (MonoError *oerror, MonoClass *klass)
1375 gpointer exception_data = mono_class_get_exception_data (klass);
1377 switch (mono_class_get_failure(klass)) {
1378 case MONO_EXCEPTION_TYPE_LOAD: {
1379 mono_error_set_type_load_class (oerror, klass, "Error Loading class");
1382 case MONO_EXCEPTION_MISSING_METHOD: {
1383 char *class_name = (char *)exception_data;
1384 char *member_name = class_name + strlen (class_name) + 1;
1386 mono_error_set_method_load (oerror, klass, member_name, "Error Loading Method");
1389 case MONO_EXCEPTION_MISSING_FIELD: {
1390 char *class_name = (char *)exception_data;
1391 char *member_name = class_name + strlen (class_name) + 1;
1393 mono_error_set_field_load (oerror, klass, member_name, "Error Loading Field");
1396 case MONO_EXCEPTION_FILE_NOT_FOUND: {
1397 char *msg_format = (char *)exception_data;
1398 char *assembly_name = msg_format + strlen (msg_format) + 1;
1399 char *msg = g_strdup_printf (msg_format, assembly_name);
1401 mono_error_set_assembly_load (oerror, assembly_name, msg);
1404 case MONO_EXCEPTION_BAD_IMAGE: {
1405 mono_error_set_bad_image (oerror, NULL, (const char *)exception_data);
1408 case MONO_EXCEPTION_INVALID_PROGRAM: {
1409 mono_error_set_invalid_program (oerror, (const char *)exception_data);
1413 g_assert_not_reached ();
1422 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1426 mono_class_alloc (MonoClass *klass, int size)
1428 if (klass->generic_class)
1429 return mono_image_set_alloc (klass->generic_class->owner, size);
1431 return mono_image_alloc (klass->image, size);
1435 mono_class_alloc0 (MonoClass *klass, int size)
1439 res = mono_class_alloc (klass, size);
1440 memset (res, 0, size);
1444 #define mono_class_new0(klass,struct_type, n_structs) \
1445 ((struct_type *) mono_class_alloc0 ((klass), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1448 * mono_class_setup_basic_field_info:
1449 * @class: The class to initialize
1451 * Initializes the klass->fields.
1452 * LOCKING: Assumes the loader lock is held.
1455 mono_class_setup_basic_field_info (MonoClass *klass)
1457 MonoClassField *field;
1465 gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
1466 image = klass->image;
1467 top = klass->field.count;
1469 if (klass->generic_class && image_is_dynamic (klass->generic_class->container_class->image) && !klass->generic_class->container_class->wastypebuilder) {
1471 * This happens when a generic instance of an unfinished generic typebuilder
1472 * is used as an element type for creating an array type. We can't initialize
1473 * the fields of this class using the fields of gklass, since gklass is not
1474 * finished yet, fields could be added to it later.
1480 mono_class_setup_basic_field_info (gtd);
1482 top = gtd->field.count;
1483 klass->field.first = gtd->field.first;
1484 klass->field.count = gtd->field.count;
1487 klass->fields = (MonoClassField *)mono_class_alloc0 (klass, sizeof (MonoClassField) * top);
1490 * Fetch all the field information.
1492 for (i = 0; i < top; i++){
1493 field = &klass->fields [i];
1494 field->parent = klass;
1497 field->name = mono_field_get_name (>d->fields [i]);
1499 int idx = klass->field.first + i;
1500 /* klass->field.first and idx points into the fieldptr table */
1501 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1502 /* The name is needed for fieldrefs */
1503 field->name = mono_metadata_string_heap (image, name_idx);
1509 * mono_class_setup_fields:
1510 * @class: The class to initialize
1512 * Initializes the klass->fields.
1513 * LOCKING: Assumes the loader lock is held.
1516 mono_class_setup_fields (MonoClass *klass)
1519 MonoImage *m = klass->image;
1521 guint32 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1522 int i, blittable = TRUE;
1523 guint32 real_size = 0;
1524 guint32 packing_size = 0;
1526 gboolean explicit_size;
1527 MonoClassField *field;
1528 MonoGenericContainer *container = NULL;
1529 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
1532 * FIXME: We have a race condition here. It's possible that this function returns
1533 * to its caller with `instance_size` set to `0` instead of the actual size. This
1534 * is not a problem when the function is called recursively on the same class,
1535 * because the size will be initialized by the outer invocation. What follows is a
1536 * description of how it can occur in other cases, too. There it is a problem,
1537 * because it can lead to the GC being asked to allocate an object of size `0`,
1538 * which SGen chokes on. The race condition is triggered infrequently by
1539 * `tests/sgen-suspend.cs`.
1541 * This function is called for a class whenever one of its subclasses is inited.
1542 * For example, it's called for every subclass of Object. What it does is this:
1544 * if (klass->setup_fields_called)
1547 * klass->instance_size = 0;
1549 * klass->setup_fields_called = 1;
1550 * ... critical point
1551 * klass->instance_size = actual_instance_size;
1553 * The last two steps are sometimes reversed, but that only changes the way in which
1554 * the race condition works.
1556 * Assume thread A goes through this function and makes it to the critical point.
1557 * Now thread B runs the function and, since `setup_fields_called` is set, returns
1558 * immediately, but `instance_size` is incorrect.
1560 * The other case looks like this:
1562 * if (klass->setup_fields_called)
1564 * ... critical point X
1565 * klass->instance_size = 0;
1566 * ... critical point Y
1567 * klass->instance_size = actual_instance_size;
1569 * klass->setup_fields_called = 1;
1571 * Assume thread A goes through the function and makes it to critical point X. Now
1572 * thread B runs through the whole of the function, returning, assuming
1573 * `instance_size` is set. At that point thread A gets to run and makes it to
1574 * critical point Y, at which time `instance_size` is `0` again, invalidating thread
1577 if (klass->setup_fields_called)
1580 if (klass->generic_class && image_is_dynamic (klass->generic_class->container_class->image) && !klass->generic_class->container_class->wastypebuilder) {
1582 * This happens when a generic instance of an unfinished generic typebuilder
1583 * is used as an element type for creating an array type. We can't initialize
1584 * the fields of this class using the fields of gklass, since gklass is not
1585 * finished yet, fields could be added to it later.
1590 mono_class_setup_basic_field_info (klass);
1591 top = klass->field.count;
1594 mono_class_setup_fields (gtd);
1595 if (mono_class_has_failure (gtd)) {
1596 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1603 klass->sizes.class_size = 0;
1605 if (klass->parent) {
1606 /* For generic instances, klass->parent might not have been initialized */
1607 mono_class_init (klass->parent);
1608 if (!klass->parent->size_inited) {
1609 mono_class_setup_fields (klass->parent);
1610 if (mono_class_has_failure (klass->parent)) {
1611 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1615 instance_size += klass->parent->instance_size;
1616 klass->min_align = klass->parent->min_align;
1617 /* we use |= since it may have been set already */
1618 klass->has_references |= klass->parent->has_references;
1619 blittable = klass->parent->blittable;
1621 instance_size = sizeof (MonoObject);
1622 klass->min_align = 1;
1625 /* We can't really enable 16 bytes alignment until the GC supports it.
1626 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1627 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1628 Bug #506144 is an example of this issue.
1630 if (klass->simd_type)
1631 klass->min_align = 16;
1633 /* Get the real size */
1634 explicit_size = mono_metadata_packing_from_typedef (klass->image, klass->type_token, &packing_size, &real_size);
1636 if (explicit_size) {
1637 if ((packing_size & 0xffffff00) != 0) {
1638 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, packing_size);
1639 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
1642 klass->packing_size = packing_size;
1643 real_size += instance_size;
1647 if (explicit_size && real_size) {
1648 instance_size = MAX (real_size, instance_size);
1650 klass->blittable = blittable;
1651 if (!klass->instance_size)
1652 klass->instance_size = instance_size;
1653 mono_memory_barrier ();
1654 klass->size_inited = 1;
1655 klass->fields_inited = 1;
1656 klass->setup_fields_called = 1;
1660 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(mono_is_corlib_image (klass->image) && !strcmp (klass->name_space, "System") && !strcmp (klass->name, "ValueType")))
1663 /* Prevent infinite loops if the class references itself */
1664 klass->setup_fields_called = 1;
1666 if (klass->generic_container) {
1667 container = klass->generic_container;
1669 container = gtd->generic_container;
1670 g_assert (container);
1674 * Fetch all the field information.
1676 for (i = 0; i < top; i++){
1677 int idx = klass->field.first + i;
1678 field = &klass->fields [i];
1680 field->parent = klass;
1683 mono_field_resolve_type (field, &error);
1684 if (!mono_error_ok (&error)) {
1685 /*mono_field_resolve_type already failed class*/
1686 mono_error_cleanup (&error);
1690 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(klass), field->name);
1691 g_assert (field->type);
1694 if (mono_field_is_deleted (field))
1697 MonoClassField *gfield = >d->fields [i];
1698 field->offset = gfield->offset;
1700 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1702 mono_metadata_field_info (m, idx, &offset, NULL, NULL);
1703 field->offset = offset;
1705 if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1706 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Missing field layout info for %s", field->name));
1709 if (field->offset < -1) { /*-1 is used to encode special static fields */
1710 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Invalid negative field offset %d for %s", field->offset, field->name));
1713 if (klass->generic_container) {
1714 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic class cannot have explicit layout."));
1720 /* Only do these checks if we still think this type is blittable */
1721 if (blittable && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1722 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1725 MonoClass *field_class = mono_class_from_mono_type (field->type);
1727 mono_class_setup_fields (field_class);
1728 if (mono_class_has_failure (field_class)) {
1729 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1733 if (!field_class || !field_class->blittable)
1738 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1739 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
1740 blittable = klass->element_class->blittable;
1743 if (mono_type_has_exceptions (field->type)) {
1744 char *class_name = mono_type_get_full_name (klass);
1745 char *type_name = mono_type_full_name (field->type);
1747 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1748 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1749 g_free (class_name);
1753 /* The def_value of fields is compute lazily during vtable creation */
1756 if (klass == mono_defaults.string_class)
1759 klass->blittable = blittable;
1761 if (klass->enumtype && !mono_class_enum_basetype (klass)) {
1762 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1765 if (explicit_size && real_size) {
1766 instance_size = MAX (real_size, instance_size);
1769 if (mono_class_has_failure (klass))
1771 mono_class_layout_fields (klass, instance_size);
1773 /*valuetypes can't be neither bigger than 1Mb or empty. */
1774 if (klass->valuetype && (klass->instance_size <= 0 || klass->instance_size > (0x100000 + sizeof (MonoObject))))
1775 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1777 mono_memory_barrier ();
1778 klass->fields_inited = 1;
1782 * mono_class_setup_fields_locking:
1783 * @class: The class to initialize
1785 * Initializes the klass->fields array of fields.
1786 * Aquires the loader lock.
1789 mono_class_setup_fields_locking (MonoClass *klass)
1791 /* This can be checked without locks */
1792 if (klass->fields_inited)
1794 mono_loader_lock ();
1795 mono_class_setup_fields (klass);
1796 mono_loader_unlock ();
1800 * mono_class_has_references:
1802 * Returns whenever @klass->has_references is set, initializing it if needed.
1803 * Aquires the loader lock.
1806 mono_class_has_references (MonoClass *klass)
1808 if (klass->init_pending) {
1809 /* Be conservative */
1812 mono_class_init (klass);
1814 return klass->has_references;
1819 * mono_type_get_basic_type_from_generic:
1822 * Returns a closed type corresponding to the possibly open type
1826 mono_type_get_basic_type_from_generic (MonoType *type)
1828 /* When we do generic sharing we let type variables stand for reference/primitive types. */
1829 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) &&
1830 (!type->data.generic_param->gshared_constraint || type->data.generic_param->gshared_constraint->type == MONO_TYPE_OBJECT))
1831 return &mono_defaults.object_class->byval_arg;
1836 type_has_references (MonoClass *klass, MonoType *ftype)
1838 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)))))
1840 if (!ftype->byref && (ftype->type == MONO_TYPE_VAR || ftype->type == MONO_TYPE_MVAR)) {
1841 MonoGenericParam *gparam = ftype->data.generic_param;
1843 if (gparam->gshared_constraint)
1844 return mono_class_has_references (mono_class_from_mono_type (gparam->gshared_constraint));
1850 * mono_class_layout_fields:
1852 * @instance_size: base instance size
1854 * Compute the placement of fields inside an object or struct, according to
1855 * the layout rules and set the following fields in @class:
1856 * - has_references (if the class contains instance references firled or structs that contain references)
1857 * - has_static_refs (same, but for static fields)
1858 * - instance_size (size of the object in memory)
1859 * - class_size (size needed for the static fields)
1860 * - size_inited (flag set when the instance_size is set)
1862 * LOCKING: this is supposed to be called with the loader lock held.
1865 mono_class_layout_fields (MonoClass *klass, int instance_size)
1868 const int top = klass->field.count;
1869 guint32 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1870 guint32 pass, passes, real_size;
1871 gboolean gc_aware_layout = FALSE;
1872 gboolean has_static_fields = FALSE;
1873 MonoClassField *field;
1876 * When we do generic sharing we need to have layout
1877 * information for open generic classes (either with a generic
1878 * context containing type variables or with a generic
1879 * container), so we don't return in that case anymore.
1883 * Enable GC aware auto layout: in this mode, reference
1884 * fields are grouped together inside objects, increasing collector
1886 * Requires that all classes whose layout is known to native code be annotated
1887 * with [StructLayout (LayoutKind.Sequential)]
1888 * Value types have gc_aware_layout disabled by default, as per
1889 * what the default is for other runtimes.
1891 /* corlib is missing [StructLayout] directives in many places */
1892 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1893 if (!klass->valuetype)
1894 gc_aware_layout = TRUE;
1897 /* Compute klass->has_references */
1899 * Process non-static fields first, since static fields might recursively
1900 * refer to the class itself.
1902 for (i = 0; i < top; i++) {
1905 field = &klass->fields [i];
1907 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1908 ftype = mono_type_get_underlying_type (field->type);
1909 ftype = mono_type_get_basic_type_from_generic (ftype);
1910 if (type_has_references (klass, ftype))
1911 klass->has_references = TRUE;
1915 for (i = 0; i < top; i++) {
1918 field = &klass->fields [i];
1920 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1921 ftype = mono_type_get_underlying_type (field->type);
1922 ftype = mono_type_get_basic_type_from_generic (ftype);
1923 if (type_has_references (klass, ftype))
1924 klass->has_static_refs = TRUE;
1928 for (i = 0; i < top; i++) {
1931 field = &klass->fields [i];
1933 ftype = mono_type_get_underlying_type (field->type);
1934 ftype = mono_type_get_basic_type_from_generic (ftype);
1935 if (type_has_references (klass, ftype)) {
1936 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1937 klass->has_static_refs = TRUE;
1939 klass->has_references = TRUE;
1944 * Compute field layout and total size (not considering static fields)
1947 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1948 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1950 if (gc_aware_layout)
1955 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1958 if (klass->parent) {
1959 mono_class_setup_fields (klass->parent);
1960 if (mono_class_has_failure (klass->parent)) {
1961 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1964 real_size = klass->parent->instance_size;
1966 real_size = sizeof (MonoObject);
1969 for (pass = 0; pass < passes; ++pass) {
1970 for (i = 0; i < top; i++){
1975 field = &klass->fields [i];
1977 if (mono_field_is_deleted (field))
1979 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1982 ftype = mono_type_get_underlying_type (field->type);
1983 ftype = mono_type_get_basic_type_from_generic (ftype);
1984 if (gc_aware_layout) {
1985 if (type_has_references (klass, ftype)) {
1994 if ((top == 1) && (klass->instance_size == sizeof (MonoObject)) &&
1995 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1996 /* This field is a hack inserted by MCS to empty structures */
2000 size = mono_type_size (field->type, &align);
2002 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
2003 align = klass->packing_size ? MIN (klass->packing_size, align): align;
2004 /* if the field has managed references, we need to force-align it
2007 if (type_has_references (klass, ftype))
2008 align = MAX (align, sizeof (gpointer));
2010 klass->min_align = MAX (align, klass->min_align);
2011 field->offset = real_size;
2013 field->offset += align - 1;
2014 field->offset &= ~(align - 1);
2016 /*TypeBuilders produce all sort of weird things*/
2017 g_assert (image_is_dynamic (klass->image) || field->offset > 0);
2018 real_size = field->offset + size;
2021 instance_size = MAX (real_size, instance_size);
2023 if (instance_size & (klass->min_align - 1)) {
2024 instance_size += klass->min_align - 1;
2025 instance_size &= ~(klass->min_align - 1);
2029 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
2033 for (i = 0; i < top; i++) {
2038 field = &klass->fields [i];
2041 * There must be info about all the fields in a type if it
2042 * uses explicit layout.
2044 if (mono_field_is_deleted (field))
2046 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2049 size = mono_type_size (field->type, &align);
2050 align = klass->packing_size ? MIN (klass->packing_size, align): align;
2051 klass->min_align = MAX (align, klass->min_align);
2054 * When we get here, field->offset is already set by the
2055 * loader (for either runtime fields or fields loaded from metadata).
2056 * The offset is from the start of the object: this works for both
2057 * classes and valuetypes.
2059 field->offset += sizeof (MonoObject);
2060 ftype = mono_type_get_underlying_type (field->type);
2061 ftype = mono_type_get_basic_type_from_generic (ftype);
2062 if (type_has_references (klass, ftype)) {
2063 if (field->offset % sizeof (gpointer)) {
2064 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
2071 real_size = MAX (real_size, size + field->offset);
2074 if (klass->has_references) {
2075 ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
2077 /* Check for overlapping reference and non-reference fields */
2078 for (i = 0; i < top; i++) {
2081 field = &klass->fields [i];
2083 if (mono_field_is_deleted (field))
2085 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2087 ftype = mono_type_get_underlying_type (field->type);
2088 if (MONO_TYPE_IS_REFERENCE (ftype))
2089 ref_bitmap [field->offset / sizeof (gpointer)] = 1;
2091 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)
2099 // FIXME: Too much code does this
2101 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field->offset / sizeof (gpointer)]) {
2102 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);
2103 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
2107 g_free (ref_bitmap);
2110 instance_size = MAX (real_size, instance_size);
2111 if (instance_size & (klass->min_align - 1)) {
2112 instance_size += klass->min_align - 1;
2113 instance_size &= ~(klass->min_align - 1);
2119 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2121 * This leads to all kinds of problems with nested structs, so only
2122 * enable it when a MONO_DEBUG property is set.
2124 * For small structs, set min_align to at least the struct size to improve
2125 * performance, and since the JIT memset/memcpy code assumes this and generates
2126 * unaligned accesses otherwise. See #78990 for a testcase.
2128 if (mono_align_small_structs) {
2129 if (instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2130 klass->min_align = MAX (klass->min_align, instance_size - sizeof (MonoObject));
2134 if (klass->instance_size && !klass->image->dynamic) {
2135 /* Might be already set using cached info */
2136 g_assert (klass->instance_size == instance_size);
2138 klass->instance_size = instance_size;
2140 mono_memory_barrier ();
2141 klass->size_inited = 1;
2144 * Compute static field layout and size
2146 for (i = 0; i < top; i++){
2150 field = &klass->fields [i];
2152 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2154 if (mono_field_is_deleted (field))
2157 if (mono_type_has_exceptions (field->type)) {
2158 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
2162 has_static_fields = TRUE;
2164 size = mono_type_size (field->type, &align);
2165 field->offset = klass->sizes.class_size;
2166 /*align is always non-zero here*/
2167 field->offset += align - 1;
2168 field->offset &= ~(align - 1);
2169 klass->sizes.class_size = field->offset + size;
2172 if (has_static_fields && klass->sizes.class_size == 0)
2173 /* Simplify code which depends on class_size != 0 if the class has static fields */
2174 klass->sizes.class_size = 8;
2178 create_array_method (MonoClass *klass, const char *name, MonoMethodSignature *sig)
2182 method = (MonoMethod *) mono_image_alloc0 (klass->image, sizeof (MonoMethodPInvoke));
2183 method->klass = klass;
2184 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2185 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2186 method->signature = sig;
2187 method->name = name;
2190 if (name [0] == '.') {
2191 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2193 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2199 * mono_class_setup_methods:
2202 * Initializes the 'methods' array in CLASS.
2203 * Calling this method should be avoided if possible since it allocates a lot
2204 * of long-living MonoMethod structures.
2205 * Methods belonging to an interface are assigned a sequential slot starting
2208 * On failure this function sets klass->exception_type
2211 mono_class_setup_methods (MonoClass *klass)
2214 MonoMethod **methods;
2219 if (klass->generic_class) {
2221 MonoClass *gklass = klass->generic_class->container_class;
2223 mono_class_init (gklass);
2224 if (!mono_class_has_failure (gklass))
2225 mono_class_setup_methods (gklass);
2226 if (mono_class_has_failure (gklass)) {
2227 /* FIXME make exception_data less opaque so it's possible to dup it here */
2228 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2232 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2233 count = gklass->method.count;
2234 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * (count + 1));
2236 for (i = 0; i < count; i++) {
2237 methods [i] = mono_class_inflate_generic_method_full_checked (
2238 gklass->methods [i], klass, mono_class_get_context (klass), &error);
2239 if (!mono_error_ok (&error)) {
2240 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2241 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)));
2244 mono_error_cleanup (&error);
2248 } else if (klass->rank) {
2250 MonoMethod *amethod;
2251 MonoMethodSignature *sig;
2252 int count_generic = 0, first_generic = 0;
2254 gboolean jagged_ctor = FALSE;
2256 count = 3 + (klass->rank > 1? 2: 1);
2258 mono_class_setup_interfaces (klass, &error);
2259 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2261 if (klass->rank == 1 && klass->element_class->rank) {
2263 klass->method.count ++;
2266 if (klass->interface_count) {
2267 count_generic = generic_array_methods (klass);
2268 first_generic = count;
2269 count += klass->interface_count * count_generic;
2272 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * count);
2274 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2275 sig->ret = &mono_defaults.void_class->byval_arg;
2276 sig->pinvoke = TRUE;
2277 sig->hasthis = TRUE;
2278 for (i = 0; i < klass->rank; ++i)
2279 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2281 amethod = create_array_method (klass, ".ctor", sig);
2282 methods [method_num++] = amethod;
2283 if (klass->rank > 1) {
2284 sig = mono_metadata_signature_alloc (klass->image, klass->rank * 2);
2285 sig->ret = &mono_defaults.void_class->byval_arg;
2286 sig->pinvoke = TRUE;
2287 sig->hasthis = TRUE;
2288 for (i = 0; i < klass->rank * 2; ++i)
2289 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2291 amethod = create_array_method (klass, ".ctor", sig);
2292 methods [method_num++] = amethod;
2296 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2297 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2298 sig->ret = &mono_defaults.void_class->byval_arg;
2299 sig->pinvoke = TRUE;
2300 sig->hasthis = TRUE;
2301 for (i = 0; i < klass->rank + 1; ++i)
2302 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2303 amethod = create_array_method (klass, ".ctor", sig);
2304 methods [method_num++] = amethod;
2307 /* element Get (idx11, [idx2, ...]) */
2308 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2309 sig->ret = &klass->element_class->byval_arg;
2310 sig->pinvoke = TRUE;
2311 sig->hasthis = TRUE;
2312 for (i = 0; i < klass->rank; ++i)
2313 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2314 amethod = create_array_method (klass, "Get", sig);
2315 methods [method_num++] = amethod;
2316 /* element& Address (idx11, [idx2, ...]) */
2317 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2318 sig->ret = &klass->element_class->this_arg;
2319 sig->pinvoke = TRUE;
2320 sig->hasthis = TRUE;
2321 for (i = 0; i < klass->rank; ++i)
2322 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2323 amethod = create_array_method (klass, "Address", sig);
2324 methods [method_num++] = amethod;
2325 /* void Set (idx11, [idx2, ...], element) */
2326 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2327 sig->ret = &mono_defaults.void_class->byval_arg;
2328 sig->pinvoke = TRUE;
2329 sig->hasthis = TRUE;
2330 for (i = 0; i < klass->rank; ++i)
2331 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2332 sig->params [i] = &klass->element_class->byval_arg;
2333 amethod = create_array_method (klass, "Set", sig);
2334 methods [method_num++] = amethod;
2336 for (i = 0; i < klass->interface_count; i++)
2337 setup_generic_array_ifaces (klass, klass->interfaces [i], methods, first_generic + i * count_generic);
2341 count = klass->method.count;
2342 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * count);
2343 for (i = 0; i < count; ++i) {
2344 int idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_METHOD, klass->method.first + i + 1);
2345 methods [i] = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | idx, klass, NULL, &error);
2347 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)));
2348 mono_error_cleanup (&error);
2353 if (MONO_CLASS_IS_INTERFACE (klass)) {
2355 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2356 for (i = 0; i < count; ++i) {
2357 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2358 methods [i]->slot = slot++;
2362 mono_image_lock (klass->image);
2364 if (!klass->methods) {
2365 klass->method.count = count;
2367 /* Needed because of the double-checking locking pattern */
2368 mono_memory_barrier ();
2370 klass->methods = methods;
2373 mono_image_unlock (klass->image);
2377 * mono_class_get_method_by_index:
2379 * Returns klass->methods [index], initializing klass->methods if neccesary.
2381 * LOCKING: Acquires the loader lock.
2384 mono_class_get_method_by_index (MonoClass *klass, int index)
2387 /* Avoid calling setup_methods () if possible */
2388 if (klass->generic_class && !klass->methods) {
2389 MonoClass *gklass = klass->generic_class->container_class;
2392 m = mono_class_inflate_generic_method_full_checked (
2393 gklass->methods [index], klass, mono_class_get_context (klass), &error);
2394 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2396 * If setup_methods () is called later for this class, no duplicates are created,
2397 * since inflate_generic_method guarantees that only one instance of a method
2398 * is created for each context.
2401 mono_class_setup_methods (klass);
2402 g_assert (m == klass->methods [index]);
2406 mono_class_setup_methods (klass);
2407 if (mono_class_has_failure (klass)) /*FIXME do proper error handling*/
2409 g_assert (index >= 0 && index < klass->method.count);
2410 return klass->methods [index];
2415 * mono_class_get_inflated_method:
2417 * Given an inflated class CLASS and a method METHOD which should be a method of
2418 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2421 mono_class_get_inflated_method (MonoClass *klass, MonoMethod *method)
2423 MonoClass *gklass = klass->generic_class->container_class;
2426 g_assert (method->klass == gklass);
2428 mono_class_setup_methods (gklass);
2429 g_assert (!mono_class_has_failure (gklass)); /*FIXME do proper error handling*/
2431 for (i = 0; i < gklass->method.count; ++i) {
2432 if (gklass->methods [i] == method) {
2433 if (klass->methods) {
2434 return klass->methods [i];
2437 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], klass, mono_class_get_context (klass), &error);
2438 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2448 * mono_class_get_vtable_entry:
2450 * Returns klass->vtable [offset], computing it if neccesary. Returns NULL on failure.
2451 * LOCKING: Acquires the loader lock.
2454 mono_class_get_vtable_entry (MonoClass *klass, int offset)
2458 if (klass->rank == 1) {
2460 * szarrays do not overwrite any methods of Array, so we can avoid
2461 * initializing their vtables in some cases.
2463 mono_class_setup_vtable (klass->parent);
2464 if (offset < klass->parent->vtable_size)
2465 return klass->parent->vtable [offset];
2468 if (klass->generic_class) {
2470 MonoClass *gklass = klass->generic_class->container_class;
2471 mono_class_setup_vtable (gklass);
2472 m = gklass->vtable [offset];
2474 m = mono_class_inflate_generic_method_full_checked (m, klass, mono_class_get_context (klass), &error);
2475 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2477 mono_class_setup_vtable (klass);
2478 if (mono_class_has_failure (klass))
2480 m = klass->vtable [offset];
2487 * mono_class_get_vtable_size:
2489 * Return the vtable size for KLASS.
2492 mono_class_get_vtable_size (MonoClass *klass)
2494 mono_class_setup_vtable (klass);
2496 return klass->vtable_size;
2500 * mono_class_setup_properties:
2502 * Initialize klass->ext.property and klass->ext.properties.
2504 * This method can fail the class.
2507 mono_class_setup_properties (MonoClass *klass)
2509 guint startm, endm, i, j;
2510 guint32 cols [MONO_PROPERTY_SIZE];
2511 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2512 MonoProperty *properties;
2516 if (klass->ext && klass->ext->properties)
2519 if (klass->generic_class) {
2520 MonoClass *gklass = klass->generic_class->container_class;
2522 mono_class_init (gklass);
2523 mono_class_setup_properties (gklass);
2524 if (mono_class_has_failure (gklass)) {
2525 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2529 properties = mono_class_new0 (klass, MonoProperty, gklass->ext->property.count + 1);
2531 for (i = 0; i < gklass->ext->property.count; i++) {
2533 MonoProperty *prop = &properties [i];
2535 *prop = gklass->ext->properties [i];
2538 prop->get = mono_class_inflate_generic_method_full_checked (
2539 prop->get, klass, mono_class_get_context (klass), &error);
2541 prop->set = mono_class_inflate_generic_method_full_checked (
2542 prop->set, klass, mono_class_get_context (klass), &error);
2544 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2545 prop->parent = klass;
2548 first = gklass->ext->property.first;
2549 count = gklass->ext->property.count;
2551 first = mono_metadata_properties_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2552 count = last - first;
2555 mono_class_setup_methods (klass);
2556 if (mono_class_has_failure (klass))
2560 properties = (MonoProperty *)mono_class_alloc0 (klass, sizeof (MonoProperty) * count);
2561 for (i = first; i < last; ++i) {
2562 mono_metadata_decode_table_row (klass->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2563 properties [i - first].parent = klass;
2564 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2565 properties [i - first].name = mono_metadata_string_heap (klass->image, cols [MONO_PROPERTY_NAME]);
2567 startm = mono_metadata_methods_from_property (klass->image, i, &endm);
2568 for (j = startm; j < endm; ++j) {
2571 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2573 if (klass->image->uncompressed_metadata) {
2575 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2576 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2577 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2579 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - klass->method.first];
2582 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2583 case METHOD_SEMANTIC_SETTER:
2584 properties [i - first].set = method;
2586 case METHOD_SEMANTIC_GETTER:
2587 properties [i - first].get = method;
2596 mono_class_alloc_ext (klass);
2598 mono_image_lock (klass->image);
2600 if (klass->ext->properties) {
2601 /* We leak 'properties' which was allocated from the image mempool */
2602 mono_image_unlock (klass->image);
2606 klass->ext->property.first = first;
2607 klass->ext->property.count = count;
2609 /* Flush any pending writes as we do double checked locking on klass->ext->properties */
2610 mono_memory_barrier ();
2612 /* Leave this assignment as the last op in the function */
2613 klass->ext->properties = properties;
2615 mono_image_unlock (klass->image);
2619 inflate_method_listz (MonoMethod **methods, MonoClass *klass, MonoGenericContext *context)
2621 MonoMethod **om, **retval;
2624 for (om = methods, count = 0; *om; ++om, ++count)
2627 retval = g_new0 (MonoMethod*, count + 1);
2629 for (om = methods, count = 0; *om; ++om, ++count) {
2631 retval [count] = mono_class_inflate_generic_method_full_checked (*om, klass, context, &error);
2632 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2638 /*This method can fail the class.*/
2640 mono_class_setup_events (MonoClass *klass)
2643 guint startm, endm, i, j;
2644 guint32 cols [MONO_EVENT_SIZE];
2645 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2649 if (klass->ext && klass->ext->events)
2652 if (klass->generic_class) {
2653 MonoClass *gklass = klass->generic_class->container_class;
2654 MonoGenericContext *context = NULL;
2656 mono_class_setup_events (gklass);
2657 if (mono_class_has_failure (gklass)) {
2658 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2662 first = gklass->ext->event.first;
2663 count = gklass->ext->event.count;
2665 events = mono_class_new0 (klass, MonoEvent, count);
2668 context = mono_class_get_context (klass);
2670 for (i = 0; i < count; i++) {
2672 MonoEvent *event = &events [i];
2673 MonoEvent *gevent = &gklass->ext->events [i];
2675 mono_error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2677 event->parent = klass;
2678 event->name = gevent->name;
2679 event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, klass, context, &error) : NULL;
2680 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2681 event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, klass, context, &error) : NULL;
2682 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2683 event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, klass, context, &error) : NULL;
2684 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2686 #ifndef MONO_SMALL_CONFIG
2687 event->other = gevent->other ? inflate_method_listz (gevent->other, klass, context) : NULL;
2689 event->attrs = gevent->attrs;
2692 first = mono_metadata_events_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2693 count = last - first;
2696 mono_class_setup_methods (klass);
2697 if (mono_class_has_failure (klass)) {
2698 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2703 events = (MonoEvent *)mono_class_alloc0 (klass, sizeof (MonoEvent) * count);
2704 for (i = first; i < last; ++i) {
2705 MonoEvent *event = &events [i - first];
2707 mono_metadata_decode_table_row (klass->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2708 event->parent = klass;
2709 event->attrs = cols [MONO_EVENT_FLAGS];
2710 event->name = mono_metadata_string_heap (klass->image, cols [MONO_EVENT_NAME]);
2712 startm = mono_metadata_methods_from_event (klass->image, i, &endm);
2713 for (j = startm; j < endm; ++j) {
2716 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2718 if (klass->image->uncompressed_metadata) {
2720 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2721 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2722 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2724 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - klass->method.first];
2727 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2728 case METHOD_SEMANTIC_ADD_ON:
2729 event->add = method;
2731 case METHOD_SEMANTIC_REMOVE_ON:
2732 event->remove = method;
2734 case METHOD_SEMANTIC_FIRE:
2735 event->raise = method;
2737 case METHOD_SEMANTIC_OTHER: {
2738 #ifndef MONO_SMALL_CONFIG
2741 if (event->other == NULL) {
2742 event->other = g_new0 (MonoMethod*, 2);
2744 while (event->other [n])
2746 event->other = (MonoMethod **)g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2748 event->other [n] = method;
2749 /* NULL terminated */
2750 event->other [n + 1] = NULL;
2761 mono_class_alloc_ext (klass);
2763 mono_image_lock (klass->image);
2765 if (klass->ext->events) {
2766 mono_image_unlock (klass->image);
2770 klass->ext->event.first = first;
2771 klass->ext->event.count = count;
2773 /* Flush any pending writes as we do double checked locking on klass->ext.events */
2774 mono_memory_barrier ();
2776 /* Leave this assignment as the last op in the function */
2777 klass->ext->events = events;
2779 mono_image_unlock (klass->image);
2783 * Global pool of interface IDs, represented as a bitset.
2784 * LOCKING: Protected by the classes lock.
2786 static MonoBitSet *global_interface_bitset = NULL;
2789 * mono_unload_interface_ids:
2790 * @bitset: bit set of interface IDs
2792 * When an image is unloaded, the interface IDs associated with
2793 * the image are put back in the global pool of IDs so the numbers
2797 mono_unload_interface_ids (MonoBitSet *bitset)
2800 mono_bitset_sub (global_interface_bitset, bitset);
2805 mono_unload_interface_id (MonoClass *klass)
2807 if (global_interface_bitset && klass->interface_id) {
2809 mono_bitset_clear (global_interface_bitset, klass->interface_id);
2815 * mono_get_unique_iid:
2818 * Assign a unique integer ID to the interface represented by @class.
2819 * The ID will positive and as small as possible.
2820 * LOCKING: Acquires the classes lock.
2821 * Returns: The new ID.
2824 mono_get_unique_iid (MonoClass *klass)
2828 g_assert (MONO_CLASS_IS_INTERFACE (klass));
2832 if (!global_interface_bitset) {
2833 global_interface_bitset = mono_bitset_new (128, 0);
2836 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2838 int old_size = mono_bitset_size (global_interface_bitset);
2839 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2840 mono_bitset_free (global_interface_bitset);
2841 global_interface_bitset = new_set;
2844 mono_bitset_set (global_interface_bitset, iid);
2845 /* set the bit also in the per-image set */
2846 if (!klass->generic_class) {
2847 if (klass->image->interface_bitset) {
2848 if (iid >= mono_bitset_size (klass->image->interface_bitset)) {
2849 MonoBitSet *new_set = mono_bitset_clone (klass->image->interface_bitset, iid + 1);
2850 mono_bitset_free (klass->image->interface_bitset);
2851 klass->image->interface_bitset = new_set;
2854 klass->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2856 mono_bitset_set (klass->image->interface_bitset, iid);
2861 #ifndef MONO_SMALL_CONFIG
2862 if (mono_print_vtable) {
2864 char *type_name = mono_type_full_name (&klass->byval_arg);
2865 if (klass->generic_class && !klass->generic_class->context.class_inst->is_open) {
2866 generic_id = klass->generic_class->context.class_inst->id;
2867 g_assert (generic_id != 0);
2871 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, klass->image->name, type_name, generic_id);
2876 g_assert (iid <= 65535);
2881 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2886 mono_class_setup_interfaces (klass, error);
2887 return_if_nok (error);
2889 for (i = 0; i < klass->interface_count; i++) {
2890 ic = klass->interfaces [i];
2893 *res = g_ptr_array_new ();
2894 g_ptr_array_add (*res, ic);
2895 mono_class_init (ic);
2896 if (mono_class_has_failure (ic)) {
2897 mono_error_set_type_load_class (error, ic, "Error Loading class");
2901 collect_implemented_interfaces_aux (ic, res, error);
2902 return_if_nok (error);
2907 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2909 GPtrArray *res = NULL;
2911 collect_implemented_interfaces_aux (klass, &res, error);
2912 if (!mono_error_ok (error)) {
2914 g_ptr_array_free (res, TRUE);
2921 compare_interface_ids (const void *p_key, const void *p_element) {
2922 const MonoClass *key = (const MonoClass *)p_key;
2923 const MonoClass *element = *(const MonoClass **)p_element;
2925 return (key->interface_id - element->interface_id);
2928 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2930 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2931 MonoClass **result = (MonoClass **)mono_binary_search (
2933 klass->interfaces_packed,
2934 klass->interface_offsets_count,
2935 sizeof (MonoClass *),
2936 compare_interface_ids);
2938 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2945 * mono_class_interface_offset_with_variance:
2947 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2948 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2950 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2952 * FIXME figure out MS disambiguation rules and fix this function.
2955 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2956 int i = mono_class_interface_offset (klass, itf);
2957 *non_exact_match = FALSE;
2961 if (!mono_class_has_variant_generic_params (itf))
2964 for (i = 0; i < klass->interface_offsets_count; i++) {
2965 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2966 *non_exact_match = TRUE;
2967 return klass->interface_offsets_packed [i];
2975 print_implemented_interfaces (MonoClass *klass) {
2978 GPtrArray *ifaces = NULL;
2980 int ancestor_level = 0;
2982 name = mono_type_get_full_name (klass);
2983 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2986 for (i = 0; i < klass->interface_offsets_count; i++)
2987 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2988 klass->interfaces_packed [i]->interface_id,
2989 klass->interface_offsets_packed [i],
2990 klass->interfaces_packed [i]->method.count,
2991 klass->interfaces_packed [i]->name_space,
2992 klass->interfaces_packed [i]->name );
2993 printf ("Interface flags: ");
2994 for (i = 0; i <= klass->max_interface_id; i++)
2995 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2996 printf ("(%d,T)", i);
2998 printf ("(%d,F)", i);
3000 printf ("Dump interface flags:");
3001 #ifdef COMPRESSED_INTERFACE_BITMAP
3003 const uint8_t* p = klass->interface_bitmap;
3004 i = klass->max_interface_id;
3006 printf (" %d x 00 %02X", p [0], p [1]);
3012 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
3013 printf (" %02X", klass->interface_bitmap [i]);
3016 while (klass != NULL) {
3017 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
3018 ifaces = mono_class_get_implemented_interfaces (klass, &error);
3019 if (!mono_error_ok (&error)) {
3020 printf (" Type failed due to %s\n", mono_error_get_message (&error));
3021 mono_error_cleanup (&error);
3022 } else if (ifaces) {
3023 for (i = 0; i < ifaces->len; i++) {
3024 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3025 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
3026 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3028 mono_class_interface_offset (klass, ic),
3033 g_ptr_array_free (ifaces, TRUE);
3036 klass = klass->parent;
3041 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
3044 args [0] = &arg0->byval_arg;
3046 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
3050 array_class_get_if_rank (MonoClass *klass, guint rank)
3052 return rank ? mono_array_class_get (klass, rank) : klass;
3056 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
3058 valuetype_types [0] = eclass;
3059 if (eclass == mono_defaults.int16_class)
3060 valuetype_types [1] = mono_defaults.uint16_class;
3061 else if (eclass == mono_defaults.uint16_class)
3062 valuetype_types [1] = mono_defaults.int16_class;
3063 else if (eclass == mono_defaults.int32_class)
3064 valuetype_types [1] = mono_defaults.uint32_class;
3065 else if (eclass == mono_defaults.uint32_class)
3066 valuetype_types [1] = mono_defaults.int32_class;
3067 else if (eclass == mono_defaults.int64_class)
3068 valuetype_types [1] = mono_defaults.uint64_class;
3069 else if (eclass == mono_defaults.uint64_class)
3070 valuetype_types [1] = mono_defaults.int64_class;
3071 else if (eclass == mono_defaults.byte_class)
3072 valuetype_types [1] = mono_defaults.sbyte_class;
3073 else if (eclass == mono_defaults.sbyte_class)
3074 valuetype_types [1] = mono_defaults.byte_class;
3075 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
3076 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
3079 /* this won't be needed once bug #325495 is completely fixed
3080 * though we'll need something similar to know which interfaces to allow
3081 * in arrays when they'll be lazyly created
3083 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
3084 * MS returns diferrent types based on which instance is called. For example:
3085 * object obj = new byte[10][];
3086 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
3087 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
3090 * Fixing this should kill quite some code, save some bits and improve compatibility.
3093 get_implicit_generic_array_interfaces (MonoClass *klass, int *num, int *is_enumerator)
3095 MonoClass *eclass = klass->element_class;
3096 static MonoClass* generic_icollection_class = NULL;
3097 static MonoClass* generic_ienumerable_class = NULL;
3098 static MonoClass* generic_ienumerator_class = NULL;
3099 static MonoClass* generic_ireadonlylist_class = NULL;
3100 static MonoClass* generic_ireadonlycollection_class = NULL;
3101 MonoClass *valuetype_types[2] = { NULL, NULL };
3102 MonoClass **interfaces = NULL;
3103 int i, nifaces, interface_count, real_count, original_rank;
3105 gboolean internal_enumerator;
3106 gboolean eclass_is_valuetype;
3108 if (!mono_defaults.generic_ilist_class) {
3112 internal_enumerator = FALSE;
3113 eclass_is_valuetype = FALSE;
3114 original_rank = eclass->rank;
3115 if (klass->byval_arg.type != MONO_TYPE_SZARRAY) {
3116 if (klass->generic_class && klass->nested_in == mono_defaults.array_class && strcmp (klass->name, "InternalEnumerator`1") == 0) {
3118 * For a Enumerator<T[]> we need to get the list of interfaces for T.
3120 eclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
3121 original_rank = eclass->rank;
3123 eclass = eclass->element_class;
3124 internal_enumerator = TRUE;
3125 *is_enumerator = TRUE;
3133 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
3134 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
3136 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
3138 if (!generic_icollection_class) {
3139 generic_icollection_class = mono_class_load_from_name (mono_defaults.corlib,
3140 "System.Collections.Generic", "ICollection`1");
3141 generic_ienumerable_class = mono_class_load_from_name (mono_defaults.corlib,
3142 "System.Collections.Generic", "IEnumerable`1");
3143 generic_ienumerator_class = mono_class_load_from_name (mono_defaults.corlib,
3144 "System.Collections.Generic", "IEnumerator`1");
3145 generic_ireadonlylist_class = mono_class_load_from_name (mono_defaults.corlib,
3146 "System.Collections.Generic", "IReadOnlyList`1");
3147 generic_ireadonlycollection_class = mono_class_load_from_name (mono_defaults.corlib,
3148 "System.Collections.Generic", "IReadOnlyCollection`1");
3151 mono_class_init (eclass);
3154 * Arrays in 2.0 need to implement a number of generic interfaces
3155 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
3156 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
3157 * We collect the types needed to build the
3158 * instantiations in interfaces at intervals of 3/5, because 3/5 are
3159 * the generic interfaces needed to implement.
3161 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
3162 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
3164 if (eclass->valuetype) {
3165 nifaces = generic_ireadonlylist_class ? 5 : 3;
3166 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
3168 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
3169 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
3170 if (internal_enumerator) {
3172 if (valuetype_types [1])
3176 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3177 interfaces [0] = valuetype_types [0];
3178 if (valuetype_types [1])
3179 interfaces [nifaces] = valuetype_types [1];
3181 eclass_is_valuetype = TRUE;
3184 int idepth = eclass->idepth;
3185 if (!internal_enumerator)
3187 nifaces = generic_ireadonlylist_class ? 2 : 3;
3189 // FIXME: This doesn't seem to work/required for generic params
3190 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
3191 mono_class_setup_interface_offsets (eclass);
3193 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
3194 /* we add object for interfaces and the supertypes for the other
3195 * types. The last of the supertypes is the element class itself which we
3196 * already created the explicit interfaces for (so we include it for IEnumerator
3197 * and exclude it for arrays).
3199 if (MONO_CLASS_IS_INTERFACE (eclass))
3202 interface_count += idepth;
3203 if (eclass->rank && eclass->element_class->valuetype) {
3204 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3205 if (valuetype_types [1])
3208 /* IList, ICollection, IEnumerable, IReadOnlyList */
3209 interface_count *= nifaces;
3210 real_count = interface_count;
3211 if (internal_enumerator) {
3212 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3213 if (valuetype_types [1])
3216 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3217 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3218 interfaces [0] = mono_defaults.object_class;
3222 for (i = 0; i < idepth; i++) {
3223 mono_class_init (eclass->supertypes [i]);
3224 interfaces [j] = eclass->supertypes [i];
3228 if (all_interfaces) {
3229 for (i = 0; i < eclass->interface_offsets_count; i++) {
3230 interfaces [j] = eclass->interfaces_packed [i];
3234 for (i = 0; i < eclass->interface_count; i++) {
3235 interfaces [j] = eclass->interfaces [i];
3239 if (valuetype_types [1]) {
3240 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3245 /* instantiate the generic interfaces */
3246 for (i = 0; i < interface_count; i += nifaces) {
3247 MonoClass *iface = interfaces [i];
3249 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3250 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3252 if (eclass->valuetype) {
3253 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3254 if (generic_ireadonlylist_class) {
3255 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3256 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3259 if (!generic_ireadonlylist_class)
3260 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3263 if (internal_enumerator) {
3265 /* instantiate IEnumerator<iface> */
3266 for (i = 0; i < interface_count; i++) {
3267 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3269 j = interface_count;
3270 if (!eclass_is_valuetype) {
3271 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3272 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3275 for (i = 0; i < eclass->idepth; i++) {
3276 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3280 for (i = 0; i < eclass->interface_offsets_count; i++) {
3281 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3285 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3287 if (valuetype_types [1])
3288 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3292 char *type_name = mono_type_get_name_full (&klass->byval_arg, 0);
3293 for (i = 0; i < real_count; ++i) {
3294 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3295 g_print ("%s implements %s\n", type_name, name);
3306 find_array_interface (MonoClass *klass, const char *name)
3309 for (i = 0; i < klass->interface_count; ++i) {
3310 if (strcmp (klass->interfaces [i]->name, name) == 0)
3317 * Return the number of virtual methods.
3318 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3319 * Return -1 on failure.
3320 * FIXME It would be nice if this information could be cached somewhere.
3323 count_virtual_methods (MonoClass *klass)
3327 klass = mono_class_get_generic_type_definition (klass); /*We can find this information by looking at the GTD*/
3329 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
3330 mono_class_setup_methods (klass);
3331 if (mono_class_has_failure (klass))
3334 for (i = 0; i < klass->method.count; ++i) {
3335 flags = klass->methods [i]->flags;
3336 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3340 for (i = 0; i < klass->method.count; ++i) {
3341 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
3343 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3351 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3359 m = (l + num_ifaces) / 2;
3360 if (interfaces_full [m] == ic)
3362 if (l == num_ifaces)
3364 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3373 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3375 int i = find_interface (num_ifaces, interfaces_full, ic);
3377 return interface_offsets_full [i];
3382 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3384 int i = find_interface (num_ifaces, interfaces_full, ic);
3388 interface_offsets_full [i] = offset;
3391 for (i = 0; i < num_ifaces; ++i) {
3392 if (interfaces_full [i]) {
3394 if (interfaces_full [i]->interface_id < ic->interface_id)
3397 while (end < num_ifaces && interfaces_full [end]) end++;
3398 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3399 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3401 interfaces_full [i] = ic;
3402 interface_offsets_full [i] = offset;
3408 #ifdef COMPRESSED_INTERFACE_BITMAP
3411 * Compressed interface bitmap design.
3413 * Interface bitmaps take a large amount of memory, because their size is
3414 * linear with the maximum interface id assigned in the process (each interface
3415 * is assigned a unique id as it is loaded). The number of interface classes
3416 * is high because of the many implicit interfaces implemented by arrays (we'll
3417 * need to lazy-load them in the future).
3418 * Most classes implement a very small number of interfaces, so the bitmap is
3419 * sparse. This bitmap needs to be checked by interface casts, so access to the
3420 * needed bit must be fast and doable with few jit instructions.
3422 * The current compression format is as follows:
3423 * *) it is a sequence of one or more two-byte elements
3424 * *) the first byte in the element is the count of empty bitmap bytes
3425 * at the current bitmap position
3426 * *) the second byte in the element is an actual bitmap byte at the current
3429 * As an example, the following compressed bitmap bytes:
3430 * 0x07 0x01 0x00 0x7
3431 * correspond to the following bitmap:
3432 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3434 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3435 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3436 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3440 * mono_compress_bitmap:
3441 * @dest: destination buffer
3442 * @bitmap: bitmap buffer
3443 * @size: size of @bitmap in bytes
3445 * This is a mono internal function.
3446 * The @bitmap data is compressed into a format that is small but
3447 * still searchable in few instructions by the JIT and runtime.
3448 * The compressed data is stored in the buffer pointed to by the
3449 * @dest array. Passing a #NULL value for @dest allows to just compute
3450 * the size of the buffer.
3451 * This compression algorithm assumes the bits set in the bitmap are
3452 * few and far between, like in interface bitmaps.
3453 * Returns: The size of the compressed bitmap in bytes.
3456 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3460 const uint8_t *end = bitmap + size;
3461 while (bitmap < end) {
3462 if (*bitmap || numz == 255) {
3486 * mono_class_interface_match:
3487 * @bitmap: a compressed bitmap buffer
3488 * @id: the index to check in the bitmap
3490 * This is a mono internal function.
3491 * Checks if a bit is set in a compressed interface bitmap. @id must
3492 * be already checked for being smaller than the maximum id encoded in the
3495 * Returns: A non-zero value if bit @id is set in the bitmap @bitmap,
3499 mono_class_interface_match (const uint8_t *bitmap, int id)
3502 id -= bitmap [0] * 8;
3506 return bitmap [1] & (1 << id);
3515 * LOCKING: this is supposed to be called with the loader lock held.
3516 * Return -1 on failure and set exception_type
3519 setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite)
3523 int i, j, max_iid, num_ifaces;
3524 MonoClass **interfaces_full = NULL;
3525 int *interface_offsets_full = NULL;
3527 GPtrArray **ifaces_array = NULL;
3528 int interface_offsets_count;
3529 MonoClass **array_interfaces = NULL;
3530 int num_array_interfaces;
3531 int is_enumerator = FALSE;
3533 mono_class_setup_supertypes (klass);
3535 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3536 * implicit interfaces have the property that they are assigned the same slot in the
3537 * vtables for compatible interfaces
3539 array_interfaces = get_implicit_generic_array_interfaces (klass, &num_array_interfaces, &is_enumerator);
3541 /* compute maximum number of slots and maximum interface id */
3543 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3544 ifaces_array = g_new0 (GPtrArray *, klass->idepth);
3545 for (j = 0; j < klass->idepth; j++) {
3546 k = klass->supertypes [j];
3547 num_ifaces += k->interface_count;
3548 for (i = 0; i < k->interface_count; i++) {
3549 ic = k->interfaces [i];
3552 mono_class_init (ic);
3554 if (max_iid < ic->interface_id)
3555 max_iid = ic->interface_id;
3557 ifaces = mono_class_get_implemented_interfaces (k, &error);
3558 if (!mono_error_ok (&error)) {
3559 char *name = mono_type_get_full_name (k);
3560 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)));
3562 mono_error_cleanup (&error);
3567 num_ifaces += ifaces->len;
3568 for (i = 0; i < ifaces->len; ++i) {
3569 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3570 if (max_iid < ic->interface_id)
3571 max_iid = ic->interface_id;
3573 ifaces_array [j] = ifaces;
3577 for (i = 0; i < num_array_interfaces; ++i) {
3578 ic = array_interfaces [i];
3579 mono_class_init (ic);
3580 if (max_iid < ic->interface_id)
3581 max_iid = ic->interface_id;
3584 if (MONO_CLASS_IS_INTERFACE (klass)) {
3586 if (max_iid < klass->interface_id)
3587 max_iid = klass->interface_id;
3589 klass->max_interface_id = max_iid;
3590 /* compute vtable offset for interfaces */
3591 interfaces_full = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3592 interface_offsets_full = (int *)g_malloc (sizeof (int) * num_ifaces);
3594 for (i = 0; i < num_ifaces; i++) {
3595 interface_offsets_full [i] = -1;
3598 /* skip the current class */
3599 for (j = 0; j < klass->idepth - 1; j++) {
3600 k = klass->supertypes [j];
3601 ifaces = ifaces_array [j];
3604 for (i = 0; i < ifaces->len; ++i) {
3606 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3608 /*Force the sharing of interface offsets between parent and subtypes.*/
3609 io = mono_class_interface_offset (k, ic);
3611 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3616 g_assert (klass == klass->supertypes [klass->idepth - 1]);
3617 ifaces = ifaces_array [klass->idepth - 1];
3619 for (i = 0; i < ifaces->len; ++i) {
3621 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3622 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3624 count = count_virtual_methods (ic);
3626 char *name = mono_type_get_full_name (ic);
3627 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error calculating interface offset of %s", name));
3636 if (MONO_CLASS_IS_INTERFACE (klass))
3637 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, klass, cur_slot, TRUE);
3639 if (num_array_interfaces) {
3640 if (is_enumerator) {
3641 int ienumerator_idx = find_array_interface (klass, "IEnumerator`1");
3642 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ienumerator_idx]);
3643 g_assert (ienumerator_offset >= 0);
3644 for (i = 0; i < num_array_interfaces; ++i) {
3645 ic = array_interfaces [i];
3646 if (strcmp (ic->name, "IEnumerator`1") == 0)
3647 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3649 g_assert_not_reached ();
3650 /*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);*/
3653 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3654 int ilist_iface_idx = find_array_interface (klass, "IList`1");
3655 MonoClass* ilist_class = klass->interfaces [ilist_iface_idx];
3656 int ireadonlylist_iface_idx = find_array_interface (klass, "IReadOnlyList`1");
3657 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? klass->interfaces [ireadonlylist_iface_idx] : NULL;
3658 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3659 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3660 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3661 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ilist_iface_idx]);
3662 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3663 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3664 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ireadonlylist_iface_idx]) : -1;
3665 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3666 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3667 for (i = 0; i < num_array_interfaces; ++i) {
3669 ic = array_interfaces [i];
3670 if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
3671 offset = ilist_offset;
3672 else if (strcmp (ic->name, "ICollection`1") == 0)
3673 offset = icollection_offset;
3674 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3675 offset = ienumerable_offset;
3676 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3677 offset = ireadonlylist_offset;
3678 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3679 offset = ireadonlycollection_offset;
3681 g_assert_not_reached ();
3682 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3683 /*g_print ("type %s has %s offset at %d (%s)\n", klass->name, ic->name, offset, klass->interfaces [0]->name);*/
3688 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3689 if (interface_offsets_full [i] != -1) {
3690 interface_offsets_count ++;
3695 * We might get called multiple times:
3696 * - mono_class_init ()
3697 * - mono_class_setup_vtable ().
3698 * - mono_class_setup_interface_offsets ().
3699 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3700 * means we have to overwrite those when called from other places (#4440).
3702 if (klass->interfaces_packed) {
3704 g_assert (klass->interface_offsets_count == interface_offsets_count);
3708 klass->interface_offsets_count = interface_offsets_count;
3709 klass->interfaces_packed = (MonoClass **)mono_class_alloc (klass, sizeof (MonoClass*) * interface_offsets_count);
3710 klass->interface_offsets_packed = (guint16 *)mono_class_alloc (klass, sizeof (guint16) * interface_offsets_count);
3711 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3712 #ifdef COMPRESSED_INTERFACE_BITMAP
3713 bitmap = g_malloc0 (bsize);
3715 bitmap = (uint8_t *)mono_class_alloc0 (klass, bsize);
3717 for (i = 0; i < interface_offsets_count; i++) {
3718 int id = interfaces_full [i]->interface_id;
3719 bitmap [id >> 3] |= (1 << (id & 7));
3720 klass->interfaces_packed [i] = interfaces_full [i];
3721 klass->interface_offsets_packed [i] = interface_offsets_full [i];
3722 /*if (num_array_interfaces)
3723 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]);*/
3725 #ifdef COMPRESSED_INTERFACE_BITMAP
3726 i = mono_compress_bitmap (NULL, bitmap, bsize);
3727 klass->interface_bitmap = mono_class_alloc0 (klass, i);
3728 mono_compress_bitmap (klass->interface_bitmap, bitmap, bsize);
3731 klass->interface_bitmap = bitmap;
3736 g_free (interfaces_full);
3737 g_free (interface_offsets_full);
3738 g_free (array_interfaces);
3739 for (i = 0; i < klass->idepth; i++) {
3740 ifaces = ifaces_array [i];
3742 g_ptr_array_free (ifaces, TRUE);
3744 g_free (ifaces_array);
3746 //printf ("JUST DONE: ");
3747 //print_implemented_interfaces (klass);
3753 * Setup interface offsets for interfaces.
3755 * - klass->max_interface_id
3756 * - klass->interface_offsets_count
3757 * - klass->interfaces_packed
3758 * - klass->interface_offsets_packed
3759 * - klass->interface_bitmap
3761 * This function can fail @class.
3764 mono_class_setup_interface_offsets (MonoClass *klass)
3766 mono_loader_lock ();
3768 setup_interface_offsets (klass, 0, FALSE);
3770 mono_loader_unlock ();
3773 /*Checks if @klass has @parent as one of it's parents type gtd
3777 * Bar<T> : Foo<Bar<Bar<T>>>
3781 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3783 klass = mono_class_get_generic_type_definition (klass);
3784 parent = mono_class_get_generic_type_definition (parent);
3785 mono_class_setup_supertypes (klass);
3786 mono_class_setup_supertypes (parent);
3788 return klass->idepth >= parent->idepth &&
3789 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3793 mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup)
3795 MonoGenericInst *ginst;
3797 if (!klass->generic_class) {
3798 mono_class_setup_vtable_full (klass, in_setup);
3799 return !mono_class_has_failure (klass);
3802 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup);
3803 if (mono_class_has_failure (klass->generic_class->container_class)) {
3804 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to load generic definition vtable"));
3808 ginst = klass->generic_class->context.class_inst;
3809 for (i = 0; i < ginst->type_argc; ++i) {
3811 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3813 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3814 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3815 if (mono_class_has_gtd_parent (klass, arg) || mono_class_has_gtd_parent (arg, klass))
3817 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3818 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Failed to load generic parameter %d", i));
3826 * mono_class_setup_vtable:
3828 * Creates the generic vtable of CLASS.
3829 * Initializes the following fields in MonoClass:
3832 * Plus all the fields initialized by setup_interface_offsets ().
3833 * If there is an error during vtable construction, klass->exception_type is set.
3835 * LOCKING: Acquires the loader lock.
3838 mono_class_setup_vtable (MonoClass *klass)
3840 mono_class_setup_vtable_full (klass, NULL);
3844 mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
3847 MonoMethod **overrides;
3848 MonoGenericContext *context;
3856 if (MONO_CLASS_IS_INTERFACE (klass)) {
3857 /* This sets method->slot for all methods if this is an interface */
3858 mono_class_setup_methods (klass);
3862 if (mono_class_has_failure (klass))
3865 if (g_list_find (in_setup, klass))
3868 mono_loader_lock ();
3870 if (klass->vtable) {
3871 mono_loader_unlock ();
3875 mono_stats.generic_vtable_count ++;
3876 in_setup = g_list_prepend (in_setup, klass);
3878 if (klass->generic_class) {
3879 if (!mono_class_check_vtable_constraints (klass, in_setup)) {
3880 mono_loader_unlock ();
3881 g_list_remove (in_setup, klass);
3885 context = mono_class_get_context (klass);
3886 type_token = klass->generic_class->container_class->type_token;
3888 context = (MonoGenericContext *) klass->generic_container;
3889 type_token = klass->type_token;
3892 if (image_is_dynamic (klass->image)) {
3893 /* Generic instances can have zero method overrides without causing any harm.
3894 * This is true since we don't do layout all over again for them, we simply inflate
3895 * the layout of the parent.
3897 mono_reflection_get_dynamic_overrides (klass, &overrides, &onum, &error);
3898 if (!is_ok (&error)) {
3899 mono_loader_unlock ();
3900 g_list_remove (in_setup, klass);
3901 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)));
3902 mono_error_cleanup (&error);
3906 /* The following call fails if there are missing methods in the type */
3907 /* FIXME it's probably a good idea to avoid this for generic instances. */
3908 ok = mono_class_get_overrides_full (klass->image, type_token, &overrides, &onum, context);
3912 mono_class_setup_vtable_general (klass, overrides, onum, in_setup);
3914 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load list of method overrides"));
3918 mono_loader_unlock ();
3919 g_list_remove (in_setup, klass);
3924 #define DEBUG_INTERFACE_VTABLE_CODE 0
3925 #define TRACE_INTERFACE_VTABLE_CODE 0
3926 #define VERIFY_INTERFACE_VTABLE_CODE 0
3927 #define VTABLE_SELECTOR (1)
3929 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3930 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3931 if (!(VTABLE_SELECTOR)) break; \
3935 #define DEBUG_INTERFACE_VTABLE(stmt)
3938 #if TRACE_INTERFACE_VTABLE_CODE
3939 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3940 if (!(VTABLE_SELECTOR)) break; \
3944 #define TRACE_INTERFACE_VTABLE(stmt)
3947 #if VERIFY_INTERFACE_VTABLE_CODE
3948 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3949 if (!(VTABLE_SELECTOR)) break; \
3953 #define VERIFY_INTERFACE_VTABLE(stmt)
3957 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3959 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3963 GString *res = g_string_new ("");
3965 g_string_append_c (res, '(');
3966 for (i = 0; i < sig->param_count; ++i) {
3968 g_string_append_c (res, ',');
3969 mono_type_get_desc (res, sig->params [i], include_namespace);
3971 g_string_append (res, ")=>");
3972 if (sig->ret != NULL) {
3973 mono_type_get_desc (res, sig->ret, include_namespace);
3975 g_string_append (res, "NULL");
3978 g_string_free (res, FALSE);
3982 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3983 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3984 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3985 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3993 is_wcf_hack_disabled (void)
3995 static gboolean disabled;
3996 static gboolean inited = FALSE;
3998 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
4005 check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
4007 MonoMethodSignature *cmsig, *imsig;
4008 if (strcmp (im->name, cm->name) == 0) {
4009 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
4010 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
4013 if (! slot_is_empty) {
4014 if (require_newslot) {
4015 if (! interface_is_explicitly_implemented_by_class) {
4016 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
4019 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4020 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
4024 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
4027 cmsig = mono_method_signature (cm);
4028 imsig = mono_method_signature (im);
4029 if (!cmsig || !imsig) {
4030 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
4034 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4035 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
4036 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4037 TRACE_INTERFACE_VTABLE (printf ("]"));
4040 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
4041 if (mono_security_core_clr_enabled ())
4042 mono_security_core_clr_check_override (klass, cm, im);
4044 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
4045 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4046 char *body_name = mono_method_full_name (cm, TRUE);
4047 char *decl_name = mono_method_full_name (im, TRUE);
4048 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));
4056 MonoClass *ic = im->klass;
4057 const char *ic_name_space = ic->name_space;
4058 const char *ic_name = ic->name;
4061 if (! require_newslot) {
4062 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
4065 if (cm->klass->rank == 0) {
4066 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
4069 cmsig = mono_method_signature (cm);
4070 imsig = mono_method_signature (im);
4071 if (!cmsig || !imsig) {
4072 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
4076 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4077 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
4078 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4079 TRACE_INTERFACE_VTABLE (printf ("]"));
4082 if (mono_class_get_image (ic) != mono_defaults.corlib) {
4083 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
4086 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
4087 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
4090 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))) {
4091 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
4095 subname = strstr (cm->name, ic_name_space);
4096 if (subname != cm->name) {
4097 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
4100 subname += strlen (ic_name_space);
4101 if (subname [0] != '.') {
4102 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
4106 if (strstr (subname, ic_name) != subname) {
4107 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
4110 subname += strlen (ic_name);
4111 if (subname [0] != '.') {
4112 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
4116 if (strcmp (subname, im->name) != 0) {
4117 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
4121 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
4122 if (mono_security_core_clr_enabled ())
4123 mono_security_core_clr_check_override (klass, cm, im);
4125 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
4126 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4127 char *body_name = mono_method_full_name (cm, TRUE);
4128 char *decl_name = mono_method_full_name (im, TRUE);
4129 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));
4139 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
4141 foreach_override (gpointer key, gpointer value, gpointer user_data) {
4142 MonoMethod *method = key;
4143 MonoMethod *override = value;
4144 MonoClass *method_class = mono_method_get_class (method);
4145 MonoClass *override_class = mono_method_get_class (override);
4147 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
4148 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
4149 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
4152 print_overrides (GHashTable *override_map, const char *message) {
4154 printf ("Override map \"%s\" START:\n", message);
4155 g_hash_table_foreach (override_map, foreach_override, NULL);
4156 printf ("Override map \"%s\" END.\n", message);
4158 printf ("Override map \"%s\" EMPTY.\n", message);
4162 print_vtable_full (MonoClass *klass, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
4163 char *full_name = mono_type_full_name (&klass->byval_arg);
4167 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
4169 if (print_interfaces) {
4170 print_implemented_interfaces (klass);
4171 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
4174 if (klass->parent) {
4175 parent_size = klass->parent->vtable_size;
4179 for (i = 0; i < size; ++i) {
4180 MonoMethod *cm = vtable [i];
4181 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
4182 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
4184 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
4192 #if VERIFY_INTERFACE_VTABLE_CODE
4194 mono_method_try_get_vtable_index (MonoMethod *method)
4196 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4197 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4198 if (imethod->declaring->is_generic)
4199 return imethod->declaring->slot;
4201 return method->slot;
4205 mono_class_verify_vtable (MonoClass *klass)
4208 char *full_name = mono_type_full_name (&klass->byval_arg);
4210 printf ("*** Verifying VTable of class '%s' \n", full_name);
4214 if (!klass->methods)
4217 for (i = 0; i < klass->method.count; ++i) {
4218 MonoMethod *cm = klass->methods [i];
4221 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4225 full_name = mono_method_full_name (cm, TRUE);
4227 slot = mono_method_try_get_vtable_index (cm);
4229 if (slot >= klass->vtable_size) {
4230 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, klass->vtable_size);
4234 if (slot >= 0 && klass->vtable [slot] != cm && (klass->vtable [slot])) {
4235 char *other_name = klass->vtable [slot] ? mono_method_full_name (klass->vtable [slot], TRUE) : g_strdup ("[null value]");
4236 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4237 g_free (other_name);
4240 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4247 print_unimplemented_interface_method_info (MonoClass *klass, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4249 char *method_signature;
4252 for (index = 0; index < onum; ++index) {
4253 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4254 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4256 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4257 type_name = mono_type_full_name (&klass->byval_arg);
4258 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4259 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4260 g_free (method_signature);
4262 mono_class_setup_methods (klass);
4263 if (mono_class_has_failure (klass)) {
4264 char *name = mono_type_get_full_name (klass);
4265 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4269 for (index = 0; index < klass->method.count; ++index) {
4270 MonoMethod *cm = klass->methods [index];
4271 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4273 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4274 g_free (method_signature);
4279 mono_method_get_method_definition (MonoMethod *method)
4281 while (method->is_inflated)
4282 method = ((MonoMethodInflated*)method)->declaring;
4287 verify_class_overrides (MonoClass *klass, MonoMethod **overrides, int onum)
4291 for (i = 0; i < onum; ++i) {
4292 MonoMethod *decl = overrides [i * 2];
4293 MonoMethod *body = overrides [i * 2 + 1];
4295 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (klass)) {
4296 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method belongs to a different class than the declared one"));
4300 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4301 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4302 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must not be static to override a base type"));
4304 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must be virtual to override a base type"));
4308 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4309 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4310 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a static method in a base type"));
4312 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a non virtual method in a base type"));
4316 if (!mono_class_is_assignable_from_slow (decl->klass, klass)) {
4317 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"));
4321 body = mono_method_get_method_definition (body);
4322 decl = mono_method_get_method_definition (decl);
4324 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4325 char *body_name = mono_method_full_name (body, TRUE);
4326 char *decl_name = mono_method_full_name (decl, TRUE);
4327 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));
4337 mono_class_need_stelemref_method (MonoClass *klass)
4339 return klass->rank == 1 && MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg);
4343 * LOCKING: this is supposed to be called with the loader lock held.
4346 mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int onum, GList *in_setup)
4350 MonoMethod **vtable;
4351 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4352 GPtrArray *ifaces = NULL;
4353 GHashTable *override_map = NULL;
4355 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4356 int first_non_interface_slot;
4358 GSList *virt_methods = NULL, *l;
4359 int stelemref_slot = 0;
4364 if (overrides && !verify_class_overrides (klass, overrides, onum))
4367 ifaces = mono_class_get_implemented_interfaces (klass, &error);
4368 if (!mono_error_ok (&error)) {
4369 char *name = mono_type_get_full_name (klass);
4370 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)));
4372 mono_error_cleanup (&error);
4374 } else if (ifaces) {
4375 for (i = 0; i < ifaces->len; i++) {
4376 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
4377 max_vtsize += ic->method.count;
4379 g_ptr_array_free (ifaces, TRUE);
4383 if (klass->parent) {
4384 mono_class_init (klass->parent);
4385 mono_class_setup_vtable_full (klass->parent, in_setup);
4387 if (mono_class_has_failure (klass->parent)) {
4388 char *name = mono_type_get_full_name (klass->parent);
4389 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Parent %s failed to load", name));
4394 max_vtsize += klass->parent->vtable_size;
4395 cur_slot = klass->parent->vtable_size;
4398 max_vtsize += klass->method.count;
4400 /*Array have a slot for stelemref*/
4401 if (mono_class_need_stelemref_method (klass)) {
4402 stelemref_slot = cur_slot;
4407 vtable = (MonoMethod **)alloca (sizeof (gpointer) * max_vtsize);
4408 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4410 /* printf ("METAINIT %s.%s\n", klass->name_space, klass->name); */
4412 cur_slot = setup_interface_offsets (klass, cur_slot, TRUE);
4413 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4416 max_iid = klass->max_interface_id;
4417 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4419 /* Optimized version for generic instances */
4420 if (klass->generic_class) {
4422 MonoClass *gklass = klass->generic_class->container_class;
4425 mono_class_setup_vtable_full (gklass, in_setup);
4426 if (mono_class_has_failure (gklass)) {
4427 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
4431 tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * gklass->vtable_size);
4432 klass->vtable_size = gklass->vtable_size;
4433 for (i = 0; i < gklass->vtable_size; ++i)
4434 if (gklass->vtable [i]) {
4435 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], klass, mono_class_get_context (klass), &error);
4436 if (!mono_error_ok (&error)) {
4437 char *err_msg = g_strdup_printf ("Could not inflate method due to %s", mono_error_get_message (&error));
4438 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
4440 mono_error_cleanup (&error);
4444 tmp [i]->slot = gklass->vtable [i]->slot;
4446 mono_memory_barrier ();
4447 klass->vtable = tmp;
4449 /* Have to set method->slot for abstract virtual methods */
4450 if (klass->methods && gklass->methods) {
4451 for (i = 0; i < klass->method.count; ++i)
4452 if (klass->methods [i]->slot == -1)
4453 klass->methods [i]->slot = gklass->methods [i]->slot;
4459 if (klass->parent && klass->parent->vtable_size) {
4460 MonoClass *parent = klass->parent;
4463 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4465 // Also inherit parent interface vtables, just as a starting point.
4466 // This is needed otherwise bug-77127.exe fails when the property methods
4467 // have different names in the iterface and the class, because for child
4468 // classes the ".override" information is not used anymore.
4469 for (i = 0; i < parent->interface_offsets_count; i++) {
4470 MonoClass *parent_interface = parent->interfaces_packed [i];
4471 int interface_offset = mono_class_interface_offset (klass, parent_interface);
4472 /*FIXME this is now dead code as this condition will never hold true.
4473 Since interface offsets are inherited then the offset of an interface implemented
4474 by a parent will never be the out of it's vtable boundary.
4476 if (interface_offset >= parent->vtable_size) {
4477 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4480 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4481 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4482 for (j = 0; j < parent_interface->method.count && !mono_class_has_failure (klass); j++) {
4483 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4484 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4485 parent_interface_offset + j, parent_interface_offset, j,
4486 interface_offset + j, interface_offset, j));
4493 /*Array have a slot for stelemref*/
4494 if (mono_class_need_stelemref_method (klass)) {
4495 MonoMethod *method = mono_marshal_get_virtual_stelemref (klass);
4497 method->slot = stelemref_slot;
4499 g_assert (method->slot == stelemref_slot);
4501 vtable [stelemref_slot] = method;
4504 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4505 /* override interface methods */
4506 for (i = 0; i < onum; i++) {
4507 MonoMethod *decl = overrides [i*2];
4508 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4510 dslot = mono_method_get_vtable_slot (decl);
4512 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
4516 dslot += mono_class_interface_offset (klass, decl->klass);
4517 vtable [dslot] = overrides [i*2 + 1];
4518 vtable [dslot]->slot = dslot;
4520 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4522 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4524 if (mono_security_core_clr_enabled ())
4525 mono_security_core_clr_check_override (klass, vtable [dslot], decl);
4528 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4529 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4532 * Create a list of virtual methods to avoid calling
4533 * mono_class_get_virtual_methods () which is slow because of the metadata
4537 gpointer iter = NULL;
4540 virt_methods = NULL;
4541 while ((cm = mono_class_get_virtual_methods (klass, &iter))) {
4542 virt_methods = g_slist_prepend (virt_methods, cm);
4544 if (mono_class_has_failure (klass))
4548 // Loop on all implemented interfaces...
4549 for (i = 0; i < klass->interface_offsets_count; i++) {
4550 MonoClass *parent = klass->parent;
4552 gboolean interface_is_explicitly_implemented_by_class;
4555 ic = klass->interfaces_packed [i];
4556 ic_offset = mono_class_interface_offset (klass, ic);
4558 mono_class_setup_methods (ic);
4559 if (mono_class_has_failure (ic))
4562 // Check if this interface is explicitly implemented (instead of just inherited)
4563 if (parent != NULL) {
4564 int implemented_interfaces_index;
4565 interface_is_explicitly_implemented_by_class = FALSE;
4566 for (implemented_interfaces_index = 0; implemented_interfaces_index < klass->interface_count; implemented_interfaces_index++) {
4567 if (ic == klass->interfaces [implemented_interfaces_index]) {
4568 interface_is_explicitly_implemented_by_class = TRUE;
4573 interface_is_explicitly_implemented_by_class = TRUE;
4576 // Loop on all interface methods...
4577 for (im_index = 0; im_index < ic->method.count; im_index++) {
4578 MonoMethod *im = ic->methods [im_index];
4579 int im_slot = ic_offset + im->slot;
4580 MonoMethod *override_im = (override_map != NULL) ? (MonoMethod *)g_hash_table_lookup (override_map, im) : NULL;
4582 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4585 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4587 // If there is an explicit implementation, just use it right away,
4588 // otherwise look for a matching method
4589 if (override_im == NULL) {
4593 // First look for a suitable method among the class methods
4594 for (l = virt_methods; l; l = l->next) {
4595 cm = (MonoMethod *)l->data;
4596 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)));
4597 if (check_interface_method_override (klass, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
4598 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4599 vtable [im_slot] = cm;
4600 /* Why do we need this? */
4605 TRACE_INTERFACE_VTABLE (printf ("\n"));
4606 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4610 // If the slot is still empty, look in all the inherited virtual methods...
4611 if ((vtable [im_slot] == NULL) && klass->parent != NULL) {
4612 MonoClass *parent = klass->parent;
4613 // Reverse order, so that last added methods are preferred
4614 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4615 MonoMethod *cm = parent->vtable [cm_index];
4617 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));
4618 if ((cm != NULL) && check_interface_method_override (klass, im, cm, FALSE, FALSE, TRUE)) {
4619 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4620 vtable [im_slot] = cm;
4621 /* Why do we need this? */
4627 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4629 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4633 g_assert (vtable [im_slot] == override_im);
4638 // If the class is not abstract, check that all its interface slots are full.
4639 // The check is done here and not directly at the end of the loop above because
4640 // it can happen (for injected generic array interfaces) that the same slot is
4641 // processed multiple times (those interfaces have overlapping slots), and it
4642 // will not always be the first pass the one that fills the slot.
4643 if (! (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4644 for (i = 0; i < klass->interface_offsets_count; i++) {
4648 ic = klass->interfaces_packed [i];
4649 ic_offset = mono_class_interface_offset (klass, ic);
4651 for (im_index = 0; im_index < ic->method.count; im_index++) {
4652 MonoMethod *im = ic->methods [im_index];
4653 int im_slot = ic_offset + im->slot;
4655 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4658 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4659 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4660 if (vtable [im_slot] == NULL) {
4661 print_unimplemented_interface_method_info (klass, ic, im, im_slot, overrides, onum);
4668 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4669 for (l = virt_methods; l; l = l->next) {
4670 cm = (MonoMethod *)l->data;
4672 * If the method is REUSE_SLOT, we must check in the
4673 * base class for a method to override.
4675 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4677 for (k = klass->parent; k ; k = k->parent) {
4682 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4683 MonoMethodSignature *cmsig, *m1sig;
4685 cmsig = mono_method_signature (cm);
4686 m1sig = mono_method_signature (m1);
4688 if (!cmsig || !m1sig) {
4689 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
4693 if (!strcmp(cm->name, m1->name) &&
4694 mono_metadata_signature_equal (cmsig, m1sig)) {
4696 if (mono_security_core_clr_enabled ())
4697 mono_security_core_clr_check_override (klass, cm, m1);
4699 slot = mono_method_get_vtable_slot (m1);
4703 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4704 char *body_name = mono_method_full_name (cm, TRUE);
4705 char *decl_name = mono_method_full_name (m1, TRUE);
4706 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));
4712 g_assert (cm->slot < max_vtsize);
4714 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4715 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4716 mono_method_full_name (m1, 1), m1,
4717 mono_method_full_name (cm, 1), cm));
4718 g_hash_table_insert (override_map, m1, cm);
4722 if (mono_class_has_failure (k))
4732 /*Non final newslot methods must be given a non-interface vtable slot*/
4733 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4737 cm->slot = cur_slot++;
4739 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4740 vtable [cm->slot] = cm;
4743 /* override non interface methods */
4744 for (i = 0; i < onum; i++) {
4745 MonoMethod *decl = overrides [i*2];
4746 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4747 g_assert (decl->slot != -1);
4748 vtable [decl->slot] = overrides [i*2 + 1];
4749 overrides [i * 2 + 1]->slot = decl->slot;
4751 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4752 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4753 mono_method_full_name (decl, 1), decl,
4754 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4755 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4757 if (mono_security_core_clr_enabled ())
4758 mono_security_core_clr_check_override (klass, vtable [decl->slot], decl);
4763 * If a method occupies more than one place in the vtable, and it is
4764 * overriden, then change the other occurances too.
4769 for (i = 0; i < max_vtsize; ++i)
4771 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4773 cm = (MonoMethod *)g_hash_table_lookup (override_map, vtable [i]);
4778 g_hash_table_destroy (override_map);
4779 override_map = NULL;
4782 g_slist_free (virt_methods);
4783 virt_methods = NULL;
4785 /* Ensure that all vtable slots are filled with concrete instance methods */
4786 if (!(klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4787 for (i = 0; i < cur_slot; ++i) {
4788 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4789 char *type_name = mono_type_get_full_name (klass);
4790 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4791 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));
4793 g_free (method_name);
4799 if (klass->generic_class) {
4800 MonoClass *gklass = klass->generic_class->container_class;
4802 mono_class_init (gklass);
4804 klass->vtable_size = MAX (gklass->vtable_size, cur_slot);
4806 /* Check that the vtable_size value computed in mono_class_init () is correct */
4807 if (klass->vtable_size)
4808 g_assert (cur_slot == klass->vtable_size);
4809 klass->vtable_size = cur_slot;
4812 /* Try to share the vtable with our parent. */
4813 if (klass->parent && (klass->parent->vtable_size == klass->vtable_size) && (memcmp (klass->parent->vtable, vtable, sizeof (gpointer) * klass->vtable_size) == 0)) {
4814 mono_memory_barrier ();
4815 klass->vtable = klass->parent->vtable;
4817 MonoMethod **tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * klass->vtable_size);
4818 memcpy (tmp, vtable, sizeof (gpointer) * klass->vtable_size);
4819 mono_memory_barrier ();
4820 klass->vtable = tmp;
4823 DEBUG_INTERFACE_VTABLE (print_vtable_full (klass, klass->vtable, klass->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4824 if (mono_print_vtable) {
4827 print_implemented_interfaces (klass);
4829 for (i = 0; i <= max_iid; i++)
4830 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
4833 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&klass->byval_arg),
4834 klass->vtable_size, icount);
4836 for (i = 0; i < cur_slot; ++i) {
4841 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4842 mono_method_full_name (cm, TRUE));
4848 printf ("Interfaces %s.%s (max_iid = %d)\n", klass->name_space,
4849 klass->name, max_iid);
4851 for (i = 0; i < klass->interface_count; i++) {
4852 ic = klass->interfaces [i];
4853 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4854 mono_class_interface_offset (klass, ic),
4855 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4858 for (k = klass->parent; k ; k = k->parent) {
4859 for (i = 0; i < k->interface_count; i++) {
4860 ic = k->interfaces [i];
4861 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4862 mono_class_interface_offset (klass, ic),
4863 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4869 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (klass));
4874 char *name = mono_type_get_full_name (klass);
4875 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("VTable setup of type %s failed", name));
4878 g_hash_table_destroy (override_map);
4880 g_slist_free (virt_methods);
4885 * mono_method_get_vtable_slot:
4887 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4888 * LOCKING: Acquires the loader lock.
4890 * FIXME Use proper MonoError machinery here.
4893 mono_method_get_vtable_slot (MonoMethod *method)
4895 if (method->slot == -1) {
4896 mono_class_setup_vtable (method->klass);
4897 if (mono_class_has_failure (method->klass))
4899 if (method->slot == -1) {
4903 if (!method->klass->generic_class) {
4904 g_assert (method->is_inflated);
4905 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4908 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4909 g_assert (method->klass->generic_class);
4910 gklass = method->klass->generic_class->container_class;
4911 mono_class_setup_methods (method->klass);
4912 g_assert (method->klass->methods);
4913 for (i = 0; i < method->klass->method.count; ++i) {
4914 if (method->klass->methods [i] == method)
4917 g_assert (i < method->klass->method.count);
4918 g_assert (gklass->methods);
4919 method->slot = gklass->methods [i]->slot;
4921 g_assert (method->slot != -1);
4923 return method->slot;
4927 * mono_method_get_vtable_index:
4930 * Returns the index into the runtime vtable to access the method or,
4931 * in the case of a virtual generic method, the virtual generic method
4932 * thunk. Returns -1 on failure.
4934 * FIXME Use proper MonoError machinery here.
4937 mono_method_get_vtable_index (MonoMethod *method)
4939 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4940 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4941 if (imethod->declaring->is_generic)
4942 return mono_method_get_vtable_slot (imethod->declaring);
4944 return mono_method_get_vtable_slot (method);
4947 static MonoMethod *default_ghc = NULL;
4948 static MonoMethod *default_finalize = NULL;
4949 static int finalize_slot = -1;
4950 static int ghc_slot = -1;
4953 initialize_object_slots (MonoClass *klass)
4958 if (klass == mono_defaults.object_class) {
4959 mono_class_setup_vtable (klass);
4960 for (i = 0; i < klass->vtable_size; ++i) {
4961 MonoMethod *cm = klass->vtable [i];
4963 if (!strcmp (cm->name, "GetHashCode"))
4965 else if (!strcmp (cm->name, "Finalize"))
4969 g_assert (ghc_slot > 0);
4970 default_ghc = klass->vtable [ghc_slot];
4972 g_assert (finalize_slot > 0);
4973 default_finalize = klass->vtable [finalize_slot];
4978 MonoMethod *array_method;
4980 } GenericArrayMethodInfo;
4982 static int generic_array_method_num = 0;
4983 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4986 generic_array_methods (MonoClass *klass)
4988 int i, count_generic = 0;
4989 GList *list = NULL, *tmp;
4990 if (generic_array_method_num)
4991 return generic_array_method_num;
4992 mono_class_setup_methods (klass->parent); /*This is setting up System.Array*/
4993 g_assert (!mono_class_has_failure (klass->parent)); /*So hitting this assert is a huge problem*/
4994 for (i = 0; i < klass->parent->method.count; i++) {
4995 MonoMethod *m = klass->parent->methods [i];
4996 if (!strncmp (m->name, "InternalArray__", 15)) {
4998 list = g_list_prepend (list, m);
5001 list = g_list_reverse (list);
5002 generic_array_method_info = (GenericArrayMethodInfo *)mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
5004 for (tmp = list; tmp; tmp = tmp->next) {
5005 const char *mname, *iname;
5007 MonoMethod *m = (MonoMethod *)tmp->data;
5008 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
5009 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
5011 generic_array_method_info [i].array_method = m;
5012 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
5013 iname = "System.Collections.Generic.ICollection`1.";
5014 mname = m->name + 27;
5015 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
5016 iname = "System.Collections.Generic.IEnumerable`1.";
5017 mname = m->name + 27;
5018 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
5019 iname = "System.Collections.Generic.IReadOnlyList`1.";
5020 mname = m->name + strlen (ireadonlylist_prefix);
5021 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
5022 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
5023 mname = m->name + strlen (ireadonlycollection_prefix);
5024 } else if (!strncmp (m->name, "InternalArray__", 15)) {
5025 iname = "System.Collections.Generic.IList`1.";
5026 mname = m->name + 15;
5028 g_assert_not_reached ();
5031 name = (gchar *)mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
5032 strcpy (name, iname);
5033 strcpy (name + strlen (iname), mname);
5034 generic_array_method_info [i].name = name;
5037 /*g_print ("array generic methods: %d\n", count_generic);*/
5039 generic_array_method_num = count_generic;
5041 return generic_array_method_num;
5045 setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos)
5047 MonoGenericContext tmp_context;
5050 tmp_context.class_inst = NULL;
5051 tmp_context.method_inst = iface->generic_class->context.class_inst;
5052 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
5054 for (i = 0; i < generic_array_method_num; i++) {
5056 MonoMethod *m = generic_array_method_info [i].array_method;
5057 MonoMethod *inflated;
5059 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
5060 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
5061 methods [pos++] = mono_marshal_get_generic_array_helper (klass, iface, generic_array_method_info [i].name, inflated);
5066 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
5068 int null_length = strlen ("(null)");
5069 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
5070 char *s = (char *)mono_image_alloc (image, len);
5073 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
5074 g_assert (result == len - 1);
5081 * @class: the class to initialize
5083 * Compute the instance_size, class_size and other infos that cannot be
5084 * computed at mono_class_get() time. Also compute vtable_size if possible.
5085 * Returns TRUE on success or FALSE if there was a problem in loading
5086 * the type (incorrect assemblies, missing assemblies, methods, etc).
5088 * LOCKING: Acquires the loader lock.
5091 mono_class_init (MonoClass *klass)
5094 MonoCachedClassInfo cached_info;
5095 gboolean has_cached_info;
5099 /* Double-checking locking pattern */
5100 if (klass->inited || mono_class_has_failure (klass))
5101 return !mono_class_has_failure (klass);
5103 /*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/
5105 /* We do everything inside the lock to prevent races */
5106 mono_loader_lock ();
5108 if (klass->inited || mono_class_has_failure (klass)) {
5109 mono_loader_unlock ();
5110 /* Somebody might have gotten in before us */
5111 return !mono_class_has_failure (klass);
5114 if (klass->init_pending) {
5115 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Recursive type definition detected"));
5119 klass->init_pending = 1;
5121 if (mono_verifier_is_enabled_for_class (klass) && !mono_verifier_verify_class (klass)) {
5122 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, concat_two_strings_with_zero (klass->image, klass->name, klass->image->assembly_name));
5127 if (klass->byval_arg.type == MONO_TYPE_ARRAY || klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5128 MonoClass *element_class = klass->element_class;
5129 if (!element_class->inited)
5130 mono_class_init (element_class);
5131 if (mono_class_has_failure (element_class)) {
5132 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5137 mono_stats.initialized_class_count++;
5139 if (klass->generic_class && !klass->generic_class->is_dynamic) {
5140 MonoClass *gklass = klass->generic_class->container_class;
5142 mono_stats.generic_class_count++;
5144 klass->method = gklass->method;
5145 klass->field = gklass->field;
5147 mono_class_init (gklass);
5148 // FIXME: Why is this needed ?
5149 if (!mono_class_has_failure (gklass))
5150 mono_class_setup_methods (gklass);
5151 if (mono_class_has_failure (gklass)) {
5152 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic Type Defintion failed to init"));
5156 if (MONO_CLASS_IS_INTERFACE (klass))
5157 klass->interface_id = mono_get_unique_iid (klass);
5160 if (klass->parent && !klass->parent->inited)
5161 mono_class_init (klass->parent);
5163 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
5165 if (klass->generic_class || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
5166 klass->nested_classes_inited = TRUE;
5169 * Computes the size used by the fields, and their locations
5171 if (has_cached_info) {
5172 klass->instance_size = cached_info.instance_size;
5173 klass->sizes.class_size = cached_info.class_size;
5174 klass->packing_size = cached_info.packing_size;
5175 klass->min_align = cached_info.min_align;
5176 klass->blittable = cached_info.blittable;
5177 klass->has_references = cached_info.has_references;
5178 klass->has_static_refs = cached_info.has_static_refs;
5179 klass->no_special_static_fields = cached_info.no_special_static_fields;
5182 if (!klass->size_inited){
5183 mono_class_setup_fields (klass);
5184 if (mono_class_has_failure (klass))
5188 /* Initialize arrays */
5190 klass->method.count = 3 + (klass->rank > 1? 2: 1);
5192 if (klass->interface_count) {
5193 int count_generic = generic_array_methods (klass);
5194 klass->method.count += klass->interface_count * count_generic;
5198 mono_class_setup_supertypes (klass);
5201 initialize_object_slots (klass);
5204 * Initialize the rest of the data without creating a generic vtable if possible.
5205 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5206 * also avoid computing a generic vtable.
5208 if (has_cached_info) {
5210 klass->vtable_size = cached_info.vtable_size;
5211 klass->has_finalize = cached_info.has_finalize;
5212 klass->has_finalize_inited = TRUE;
5213 klass->ghcimpl = cached_info.ghcimpl;
5214 klass->has_cctor = cached_info.has_cctor;
5215 } else if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5216 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5217 * The first slot if for array with.
5219 static int szarray_vtable_size[2] = { 0 };
5221 int slot = MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg) ? 0 : 1;
5224 if (!szarray_vtable_size [slot]) {
5225 mono_class_setup_vtable (klass);
5226 szarray_vtable_size [slot] = klass->vtable_size;
5228 klass->vtable_size = szarray_vtable_size[slot];
5230 } else if (klass->generic_class && !MONO_CLASS_IS_INTERFACE (klass)) {
5231 MonoClass *gklass = klass->generic_class->container_class;
5233 /* Generic instance case */
5234 klass->ghcimpl = gklass->ghcimpl;
5235 klass->has_cctor = gklass->has_cctor;
5237 mono_class_setup_vtable (gklass);
5238 if (mono_class_has_failure (gklass)) {
5239 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5243 klass->vtable_size = gklass->vtable_size;
5247 /* ghcimpl is not currently used
5249 if (klass->parent) {
5250 MonoMethod *cmethod = klass->vtable [ghc_slot];
5251 if (cmethod->is_inflated)
5252 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5253 if (cmethod == default_ghc) {
5259 /* C# doesn't allow interfaces to have cctors */
5260 if (!MONO_CLASS_IS_INTERFACE (klass) || klass->image != mono_defaults.corlib) {
5261 MonoMethod *cmethod = NULL;
5263 if (klass->type_token && !image_is_dynamic(klass->image)) {
5264 cmethod = find_method_in_metadata (klass, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5265 /* The find_method function ignores the 'flags' argument */
5266 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5267 klass->has_cctor = 1;
5269 mono_class_setup_methods (klass);
5270 if (mono_class_has_failure (klass))
5273 for (i = 0; i < klass->method.count; ++i) {
5274 MonoMethod *method = klass->methods [i];
5275 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5276 (strcmp (".cctor", method->name) == 0)) {
5277 klass->has_cctor = 1;
5285 if (klass->parent) {
5286 int first_iface_slot;
5287 /* This will compute klass->parent->vtable_size for some classes */
5288 mono_class_init (klass->parent);
5289 if (mono_class_has_failure (klass->parent)) {
5290 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5293 if (!klass->parent->vtable_size) {
5294 /* FIXME: Get rid of this somehow */
5295 mono_class_setup_vtable (klass->parent);
5296 if (mono_class_has_failure (klass->parent)) {
5297 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5301 first_iface_slot = klass->parent->vtable_size;
5302 if (mono_class_need_stelemref_method (klass))
5304 setup_interface_offsets (klass, first_iface_slot, TRUE);
5306 setup_interface_offsets (klass, 0, TRUE);
5309 if (mono_security_core_clr_enabled ())
5310 mono_security_core_clr_check_inheritance (klass);
5312 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass))
5313 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Invalid generic instantiation"));
5318 /* Because of the double-checking locking pattern */
5319 mono_memory_barrier ();
5321 klass->init_pending = 0;
5323 mono_loader_unlock ();
5325 return !mono_class_has_failure (klass);
5329 * mono_class_has_finalizer:
5331 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5335 mono_class_has_finalizer (MonoClass *klass)
5337 gboolean has_finalize = FALSE;
5339 if (klass->has_finalize_inited)
5340 return klass->has_finalize;
5342 /* Interfaces and valuetypes are not supposed to have finalizers */
5343 if (!(MONO_CLASS_IS_INTERFACE (klass) || klass->valuetype)) {
5344 MonoMethod *cmethod = NULL;
5346 if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5347 } else if (klass->generic_class) {
5348 MonoClass *gklass = klass->generic_class->container_class;
5350 has_finalize = mono_class_has_finalizer (gklass);
5351 } else if (klass->parent && klass->parent->has_finalize) {
5352 has_finalize = TRUE;
5354 if (klass->parent) {
5356 * Can't search in metadata for a method named Finalize, because that
5357 * ignores overrides.
5359 mono_class_setup_vtable (klass);
5360 if (mono_class_has_failure (klass))
5363 cmethod = klass->vtable [finalize_slot];
5367 g_assert (klass->vtable_size > finalize_slot);
5369 if (klass->parent) {
5370 if (cmethod->is_inflated)
5371 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5372 if (cmethod != default_finalize)
5373 has_finalize = TRUE;
5379 mono_image_lock (klass->image);
5381 if (!klass->has_finalize_inited) {
5382 klass->has_finalize = has_finalize ? 1 : 0;
5384 mono_memory_barrier ();
5385 klass->has_finalize_inited = TRUE;
5388 mono_image_unlock (klass->image);
5390 return klass->has_finalize;
5394 mono_is_corlib_image (MonoImage *image)
5396 /* FIXME: allow the dynamic case for our compilers and with full trust */
5397 if (image_is_dynamic (image))
5398 return image->assembly && !strcmp (image->assembly->aname.name, "mscorlib");
5400 return image == mono_defaults.corlib;
5404 * LOCKING: this assumes the loader lock is held
5407 mono_class_setup_mono_type (MonoClass *klass)
5409 const char *name = klass->name;
5410 const char *nspace = klass->name_space;
5411 gboolean is_corlib = mono_is_corlib_image (klass->image);
5413 klass->this_arg.byref = 1;
5414 klass->this_arg.data.klass = klass;
5415 klass->this_arg.type = MONO_TYPE_CLASS;
5416 klass->byval_arg.data.klass = klass;
5417 klass->byval_arg.type = MONO_TYPE_CLASS;
5419 if (is_corlib && !strcmp (nspace, "System")) {
5420 if (!strcmp (name, "ValueType")) {
5422 * do not set the valuetype bit for System.ValueType.
5423 * klass->valuetype = 1;
5425 klass->blittable = TRUE;
5426 } else if (!strcmp (name, "Enum")) {
5428 * do not set the valuetype bit for System.Enum.
5429 * klass->valuetype = 1;
5431 klass->valuetype = 0;
5432 klass->enumtype = 0;
5433 } else if (!strcmp (name, "Object")) {
5434 klass->byval_arg.type = MONO_TYPE_OBJECT;
5435 klass->this_arg.type = MONO_TYPE_OBJECT;
5436 } else if (!strcmp (name, "String")) {
5437 klass->byval_arg.type = MONO_TYPE_STRING;
5438 klass->this_arg.type = MONO_TYPE_STRING;
5439 } else if (!strcmp (name, "TypedReference")) {
5440 klass->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5441 klass->this_arg.type = MONO_TYPE_TYPEDBYREF;
5445 if (klass->valuetype) {
5446 int t = MONO_TYPE_VALUETYPE;
5448 if (is_corlib && !strcmp (nspace, "System")) {
5451 if (!strcmp (name, "Boolean")) {
5452 t = MONO_TYPE_BOOLEAN;
5453 } else if (!strcmp(name, "Byte")) {
5455 klass->blittable = TRUE;
5459 if (!strcmp (name, "Char")) {
5464 if (!strcmp (name, "Double")) {
5466 klass->blittable = TRUE;
5470 if (!strcmp (name, "Int32")) {
5472 klass->blittable = TRUE;
5473 } else if (!strcmp(name, "Int16")) {
5475 klass->blittable = TRUE;
5476 } else if (!strcmp(name, "Int64")) {
5478 klass->blittable = TRUE;
5479 } else if (!strcmp(name, "IntPtr")) {
5481 klass->blittable = TRUE;
5485 if (!strcmp (name, "Single")) {
5487 klass->blittable = TRUE;
5488 } else if (!strcmp(name, "SByte")) {
5490 klass->blittable = TRUE;
5494 if (!strcmp (name, "UInt32")) {
5496 klass->blittable = TRUE;
5497 } else if (!strcmp(name, "UInt16")) {
5499 klass->blittable = TRUE;
5500 } else if (!strcmp(name, "UInt64")) {
5502 klass->blittable = TRUE;
5503 } else if (!strcmp(name, "UIntPtr")) {
5505 klass->blittable = TRUE;
5509 if (!strcmp (name, "TypedReference")) {
5510 t = MONO_TYPE_TYPEDBYREF;
5511 klass->blittable = TRUE;
5515 if (!strcmp (name, "Void")) {
5523 klass->byval_arg.type = (MonoTypeEnum)t;
5524 klass->this_arg.type = (MonoTypeEnum)t;
5527 if (MONO_CLASS_IS_INTERFACE (klass))
5528 klass->interface_id = mono_get_unique_iid (klass);
5534 * COM initialization is delayed until needed.
5535 * However when a [ComImport] attribute is present on a type it will trigger
5536 * the initialization. This is not a problem unless the BCL being executed
5537 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5540 init_com_from_comimport (MonoClass *klass)
5542 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5543 if (mono_security_core_clr_enabled ()) {
5544 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5545 if (!mono_security_core_clr_determine_platform_image (klass->image)) {
5546 /* but it can not be made available for application (i.e. user code) since all COM calls
5547 * are considered native calls. In this case we fail with a TypeLoadException (just like
5548 * Silverlight 2 does */
5549 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5554 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5556 #endif /*DISABLE_COM*/
5559 * LOCKING: this assumes the loader lock is held
5562 mono_class_setup_parent (MonoClass *klass, MonoClass *parent)
5564 gboolean system_namespace;
5565 gboolean is_corlib = mono_is_corlib_image (klass->image);
5567 system_namespace = !strcmp (klass->name_space, "System") && is_corlib;
5569 /* if root of the hierarchy */
5570 if (system_namespace && !strcmp (klass->name, "Object")) {
5571 klass->parent = NULL;
5572 klass->instance_size = sizeof (MonoObject);
5575 if (!strcmp (klass->name, "<Module>")) {
5576 klass->parent = NULL;
5577 klass->instance_size = 0;
5581 if (!MONO_CLASS_IS_INTERFACE (klass)) {
5582 /* Imported COM Objects always derive from __ComObject. */
5584 if (MONO_CLASS_IS_IMPORT (klass)) {
5585 init_com_from_comimport (klass);
5586 if (parent == mono_defaults.object_class)
5587 parent = mono_class_get_com_object_class ();
5591 /* set the parent to something useful and safe, but mark the type as broken */
5592 parent = mono_defaults.object_class;
5593 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5597 klass->parent = parent;
5599 if (parent->generic_class && !parent->name) {
5601 * If the parent is a generic instance, we may get
5602 * called before it is fully initialized, especially
5603 * before it has its name.
5608 #ifndef DISABLE_REMOTING
5609 klass->marshalbyref = parent->marshalbyref;
5610 klass->contextbound = parent->contextbound;
5613 klass->delegate = parent->delegate;
5615 if (MONO_CLASS_IS_IMPORT (klass) || mono_class_is_com_object (parent))
5616 mono_class_set_is_com_object (klass);
5618 if (system_namespace) {
5619 #ifndef DISABLE_REMOTING
5620 if (klass->name [0] == 'M' && !strcmp (klass->name, "MarshalByRefObject"))
5621 klass->marshalbyref = 1;
5623 if (klass->name [0] == 'C' && !strcmp (klass->name, "ContextBoundObject"))
5624 klass->contextbound = 1;
5626 if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate"))
5627 klass->delegate = 1;
5630 if (klass->parent->enumtype || (mono_is_corlib_image (klass->parent->image) && (strcmp (klass->parent->name, "ValueType") == 0) &&
5631 (strcmp (klass->parent->name_space, "System") == 0)))
5632 klass->valuetype = 1;
5633 if (mono_is_corlib_image (klass->parent->image) && ((strcmp (klass->parent->name, "Enum") == 0) && (strcmp (klass->parent->name_space, "System") == 0))) {
5634 klass->valuetype = klass->enumtype = 1;
5636 /*klass->enumtype = klass->parent->enumtype; */
5638 /* initialize com types if COM interfaces are present */
5640 if (MONO_CLASS_IS_IMPORT (klass))
5641 init_com_from_comimport (klass);
5643 klass->parent = NULL;
5649 * mono_class_setup_supertypes:
5652 * Build the data structure needed to make fast type checks work.
5653 * This currently sets two fields in @class:
5654 * - idepth: distance between @class and System.Object in the type
5656 * - supertypes: array of classes: each element has a class in the hierarchy
5657 * starting from @class up to System.Object
5659 * LOCKING: This function is atomic, in case of contention we waste memory.
5662 mono_class_setup_supertypes (MonoClass *klass)
5665 MonoClass **supertypes;
5667 mono_atomic_load_acquire (supertypes, MonoClass **, &klass->supertypes);
5671 if (klass->parent && !klass->parent->supertypes)
5672 mono_class_setup_supertypes (klass->parent);
5674 klass->idepth = klass->parent->idepth + 1;
5678 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, klass->idepth);
5679 supertypes = (MonoClass **)mono_class_alloc0 (klass, sizeof (MonoClass *) * ms);
5681 if (klass->parent) {
5682 CHECKED_METADATA_WRITE_PTR ( supertypes [klass->idepth - 1] , klass );
5685 for (supertype_idx = 0; supertype_idx < klass->parent->idepth; supertype_idx++)
5686 CHECKED_METADATA_WRITE_PTR ( supertypes [supertype_idx] , klass->parent->supertypes [supertype_idx] );
5688 CHECKED_METADATA_WRITE_PTR ( supertypes [0] , klass );
5691 CHECKED_METADATA_WRITE_PTR_ATOMIC ( klass->supertypes , supertypes );
5695 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5697 MonoClass *gtd = (MonoClass*)user_data;
5698 /* Only try to fix generic instances of @gtd */
5699 if (gclass->generic_class->container_class != gtd)
5702 /* Check if the generic instance has no parent. */
5703 if (gtd->parent && !gclass->parent)
5704 mono_generic_class_setup_parent (gclass, gtd);
5710 mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char *msg)
5712 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (msg));
5713 mono_error_set_type_load_class (error, klass, msg);
5717 * mono_class_create_from_typedef:
5718 * @image: image where the token is valid
5719 * @type_token: typedef token
5720 * @error: used to return any error found while creating the type
5722 * Create the MonoClass* representing the specified type token.
5723 * @type_token must be a TypeDef token.
5725 * FIXME: don't return NULL on failure, just the the caller figure it out.
5728 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5730 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5731 MonoClass *klass, *parent = NULL;
5732 guint32 cols [MONO_TYPEDEF_SIZE];
5733 guint32 cols_next [MONO_TYPEDEF_SIZE];
5734 guint tidx = mono_metadata_token_index (type_token);
5735 MonoGenericContext *context = NULL;
5736 const char *name, *nspace;
5738 MonoClass **interfaces;
5739 guint32 field_last, method_last;
5740 guint32 nesting_tokeen;
5742 mono_error_init (error);
5744 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5745 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5749 mono_loader_lock ();
5751 if ((klass = (MonoClass *)mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5752 mono_loader_unlock ();
5756 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5758 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5759 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5761 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
5764 klass->name_space = nspace;
5766 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5768 klass->image = image;
5769 klass->type_token = type_token;
5770 klass->flags = cols [MONO_TYPEDEF_FLAGS];
5772 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
5774 classes_size += sizeof (MonoClass);
5777 * Check whether we're a generic type definition.
5779 klass->generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
5780 if (klass->generic_container) {
5781 klass->is_generic = 1;
5782 klass->generic_container->owner.klass = klass;
5783 klass->generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
5784 context = &klass->generic_container->context;
5787 if (klass->generic_container)
5788 enable_gclass_recording ();
5790 if (cols [MONO_TYPEDEF_EXTENDS]) {
5792 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5794 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5795 /*WARNING: this must satisfy mono_metadata_type_hash*/
5796 klass->this_arg.byref = 1;
5797 klass->this_arg.data.klass = klass;
5798 klass->this_arg.type = MONO_TYPE_CLASS;
5799 klass->byval_arg.data.klass = klass;
5800 klass->byval_arg.type = MONO_TYPE_CLASS;
5802 parent = mono_class_get_checked (image, parent_token, error);
5803 if (parent && context) /* Always inflate */
5804 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5806 if (parent == NULL) {
5807 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5808 goto parent_failure;
5811 for (tmp = parent; tmp; tmp = tmp->parent) {
5813 mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
5814 goto parent_failure;
5816 if (klass->generic_container && tmp->generic_class && tmp->generic_class->container_class == klass) {
5817 mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
5818 goto parent_failure;
5823 mono_class_setup_parent (klass, parent);
5825 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5826 mono_class_setup_mono_type (klass);
5828 if (klass->generic_container)
5829 disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
5832 * This might access klass->byval_arg for recursion generated by generic constraints,
5833 * so it has to come after setup_mono_type ().
5835 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5836 klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5837 if (!mono_error_ok (error)) {
5838 /*FIXME implement a mono_class_set_failure_from_mono_error */
5839 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5840 mono_loader_unlock ();
5841 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5846 if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5850 if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5854 klass->cast_class = klass->element_class = klass;
5856 if (!klass->enumtype) {
5857 if (!mono_metadata_interfaces_from_typedef_full (
5858 image, type_token, &interfaces, &icount, FALSE, context, error)){
5860 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5861 mono_loader_unlock ();
5862 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5866 klass->interfaces = interfaces;
5867 klass->interface_count = icount;
5868 klass->interfaces_inited = 1;
5871 /*g_print ("Load class %s\n", name);*/
5874 * Compute the field and method lists
5876 klass->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5877 klass->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5879 if (tt->rows > tidx){
5880 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5881 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5882 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5884 field_last = image->tables [MONO_TABLE_FIELD].rows;
5885 method_last = image->tables [MONO_TABLE_METHOD].rows;
5888 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5889 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5890 klass->field.count = field_last - klass->field.first;
5892 klass->field.count = 0;
5894 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5895 klass->method.count = method_last - klass->method.first;
5897 klass->method.count = 0;
5899 /* reserve space to store vector pointer in arrays */
5900 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5901 klass->instance_size += 2 * sizeof (gpointer);
5902 g_assert (klass->field.count == 0);
5905 if (klass->enumtype) {
5906 MonoType *enum_basetype = mono_class_find_enum_basetype (klass, error);
5907 if (!enum_basetype) {
5908 /*set it to a default value as the whole runtime can't handle this to be null*/
5909 klass->cast_class = klass->element_class = mono_defaults.int32_class;
5910 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5911 mono_loader_unlock ();
5912 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5915 klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
5919 * If we're a generic type definition, load the constraints.
5920 * We must do this after the class has been constructed to make certain recursive scenarios
5923 if (klass->generic_container && !mono_metadata_load_generic_param_constraints_checked (image, type_token, klass->generic_container, error)) {
5924 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)));
5925 mono_loader_unlock ();
5926 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5930 if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5931 if (!strncmp (name, "Vector", 6))
5932 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");
5935 mono_loader_unlock ();
5937 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5942 mono_class_setup_mono_type (klass);
5943 mono_loader_unlock ();
5944 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5948 /** Is klass a Nullable<T> ginst? */
5950 mono_class_is_nullable (MonoClass *klass)
5952 return klass->generic_class != NULL &&
5953 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5957 /** if klass is T? return T */
5959 mono_class_get_nullable_param (MonoClass *klass)
5961 g_assert (mono_class_is_nullable (klass));
5962 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5966 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5970 MonoGenericClass *gclass = klass->generic_class;
5972 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5973 if (!mono_error_ok (&error)) {
5974 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5975 klass->parent = mono_defaults.object_class;
5976 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5977 mono_error_cleanup (&error);
5981 mono_class_setup_parent (klass, klass->parent);
5983 if (klass->enumtype) {
5984 klass->cast_class = gtd->cast_class;
5985 klass->element_class = gtd->element_class;
5991 * Create the `MonoClass' for an instantiation of a generic type.
5992 * We only do this if we actually need it.
5995 mono_generic_class_get_class (MonoGenericClass *gclass)
5997 MonoClass *klass, *gklass;
5999 if (gclass->cached_class)
6000 return gclass->cached_class;
6002 mono_loader_lock ();
6003 if (gclass->cached_class) {
6004 mono_loader_unlock ();
6005 return gclass->cached_class;
6008 klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
6010 gklass = gclass->container_class;
6012 if (record_gclass_instantiation > 0)
6013 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
6015 if (gklass->nested_in) {
6016 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
6017 klass->nested_in = gklass->nested_in;
6020 klass->name = gklass->name;
6021 klass->name_space = gklass->name_space;
6023 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6025 klass->image = gklass->image;
6026 klass->flags = gklass->flags;
6027 klass->type_token = gklass->type_token;
6028 klass->field.count = gklass->field.count;
6030 klass->is_inflated = 1;
6031 klass->generic_class = gclass;
6033 klass->byval_arg.type = MONO_TYPE_GENERICINST;
6034 klass->this_arg.type = klass->byval_arg.type;
6035 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
6036 klass->this_arg.byref = TRUE;
6037 klass->enumtype = gklass->enumtype;
6038 klass->valuetype = gklass->valuetype;
6040 klass->cast_class = klass->element_class = klass;
6042 if (mono_class_is_nullable (klass))
6043 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
6046 * We're not interested in the nested classes of a generic instance.
6047 * We use the generic type definition to look for nested classes.
6050 mono_generic_class_setup_parent (klass, gklass);
6052 if (gclass->is_dynamic) {
6054 * 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.
6055 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
6056 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
6058 if (!gklass->wastypebuilder)
6061 mono_class_setup_supertypes (klass);
6063 if (klass->enumtype) {
6065 * For enums, gklass->fields might not been set, but instance_size etc. is
6066 * already set in mono_reflection_create_internal_class (). For non-enums,
6067 * these will be computed normally in mono_class_layout_fields ().
6069 klass->instance_size = gklass->instance_size;
6070 klass->sizes.class_size = gklass->sizes.class_size;
6071 mono_memory_barrier ();
6072 klass->size_inited = 1;
6076 mono_memory_barrier ();
6077 gclass->cached_class = klass;
6079 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6081 inflated_classes ++;
6082 inflated_classes_size += sizeof (MonoClass);
6084 mono_loader_unlock ();
6090 get_image_for_container (MonoGenericContainer *container)
6093 if (container->is_anonymous) {
6094 result = container->owner.image;
6097 if (container->is_method) {
6098 MonoMethod *method = container->owner.method;
6099 g_assert_checked (method);
6100 klass = method->klass;
6102 klass = container->owner.klass;
6104 g_assert_checked (klass);
6105 result = klass->image;
6112 get_image_for_generic_param (MonoGenericParam *param)
6114 MonoGenericContainer *container = mono_generic_param_owner (param);
6115 g_assert_checked (container);
6116 return get_image_for_container (container);
6119 // Make a string in the designated image consisting of a single integer.
6120 #define INT_STRING_SIZE 16
6122 make_generic_name_string (MonoImage *image, int num)
6124 char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
6125 g_snprintf (name, INT_STRING_SIZE, "%d", num);
6129 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
6130 // pinfo is derived from param by the caller for us.
6132 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
6134 MonoClass *klass, **ptr;
6136 MonoGenericContainer *container = mono_generic_param_owner (param);
6137 g_assert_checked (container);
6139 MonoImage *image = get_image_for_container (container);
6140 gboolean is_mvar = container->is_method;
6141 gboolean is_anonymous = container->is_anonymous;
6143 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6144 classes_size += sizeof (MonoClass);
6147 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
6149 int n = mono_generic_param_num (param);
6150 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
6154 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , "" );
6155 } else if (is_mvar) {
6156 MonoMethod *omethod = container->owner.method;
6157 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
6159 MonoClass *oklass = container->owner.klass;
6160 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
6163 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6165 // Count non-NULL items in pinfo->constraints
6168 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6172 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6173 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
6175 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
6176 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
6178 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
6181 if (count - pos > 0) {
6182 klass->interface_count = count - pos;
6183 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
6184 klass->interfaces_inited = TRUE;
6185 for (i = pos; i < count; i++)
6186 CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
6189 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
6191 klass->inited = TRUE;
6192 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class , klass );
6193 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
6194 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
6196 klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6197 klass->this_arg.type = klass->byval_arg.type;
6198 CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param , param );
6199 CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
6200 klass->this_arg.byref = TRUE;
6202 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6203 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6205 /*Init these fields to sane values*/
6206 klass->min_align = 1;
6208 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6209 * constrained to, the JIT depends on this.
6211 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6212 mono_memory_barrier ();
6213 klass->size_inited = 1;
6214 klass->setup_fields_called = 1;
6216 mono_class_setup_supertypes (klass);
6218 if (count - pos > 0) {
6219 mono_class_setup_vtable (klass->parent);
6220 if (mono_class_has_failure (klass->parent))
6221 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
6223 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6229 #define FAST_CACHE_SIZE 16
6232 * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6233 * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6234 * we cache the MonoClasses.
6235 * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6236 * LOCKING: Takes the image lock depending on @take_lock.
6239 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6241 int n = mono_generic_param_num (param);
6242 MonoImage *image = get_image_for_generic_param (param);
6243 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6244 MonoClass *klass = NULL;
6249 // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6250 // For high numbers or constraints we have to use pointer hashes.
6251 if (param->gshared_constraint) {
6252 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6255 mono_image_lock (image);
6256 klass = (MonoClass *)g_hash_table_lookup (ht, param);
6258 mono_image_unlock (image);
6263 if (n < FAST_CACHE_SIZE) {
6265 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6267 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6269 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6272 mono_image_lock (image);
6273 klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6275 mono_image_unlock (image);
6282 * LOCKING: Image lock (param->image) must be held
6285 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6287 int n = mono_generic_param_num (param);
6288 MonoImage *image = get_image_for_generic_param (param);
6289 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6293 if (param->gshared_constraint) {
6294 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6296 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6297 mono_memory_barrier ();
6299 image->mvar_cache_constrained = ht;
6301 image->var_cache_constrained = ht;
6303 g_hash_table_insert (ht, param, klass);
6304 } else if (n < FAST_CACHE_SIZE) {
6306 /* Requires locking to avoid droping an already published class */
6307 if (!image->mvar_cache_fast)
6308 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6309 image->mvar_cache_fast [n] = klass;
6311 if (!image->var_cache_fast)
6312 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6313 image->var_cache_fast [n] = klass;
6316 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6318 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6320 ht = g_hash_table_new (NULL, NULL);
6321 mono_memory_barrier ();
6323 image->mvar_cache_slow = ht;
6325 image->var_cache_slow = ht;
6328 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6333 * LOCKING: Acquires the image lock (@image).
6336 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6338 MonoImage *image = get_image_for_generic_param (param);
6339 MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6340 MonoClass *klass, *klass2;
6342 // If a klass already exists for this object and is cached, return it.
6343 if (pinfo) // Non-anonymous
6344 klass = pinfo->pklass;
6346 klass = get_anon_gparam_class (param, TRUE);
6351 // Create a new klass
6352 klass = make_generic_param_class (param, pinfo);
6354 // Now we need to cache the klass we created.
6355 // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6356 // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6357 // and allow our newly-created klass object to just leak.
6358 mono_memory_barrier ();
6360 mono_image_lock (image);
6362 // Here "klass2" refers to the klass potentially created by the other thread.
6363 if (pinfo) // Repeat check from above
6364 klass2 = pinfo->pklass;
6366 klass2 = get_anon_gparam_class (param, FALSE);
6373 pinfo->pklass = klass;
6375 set_anon_gparam_class (param, klass);
6377 mono_image_unlock (image);
6379 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6381 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED); // Alert profiler about botched class create
6383 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6389 * mono_class_from_generic_parameter:
6390 * @param: Parameter to find/construct a class for.
6391 * @arg2: Is ignored.
6392 * @arg3: Is ignored.
6395 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6397 return mono_class_from_generic_parameter_internal (param);
6402 mono_ptr_class_get (MonoType *type)
6405 MonoClass *el_class;
6409 el_class = mono_class_from_mono_type (type);
6410 image = el_class->image;
6412 mono_image_lock (image);
6413 if (image->ptr_cache) {
6414 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6415 mono_image_unlock (image);
6419 mono_image_unlock (image);
6421 result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6423 classes_size += sizeof (MonoClass);
6425 result->parent = NULL; /* no parent for PTR types */
6426 result->name_space = el_class->name_space;
6427 name = g_strdup_printf ("%s*", el_class->name);
6428 result->name = mono_image_strdup (image, name);
6431 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6433 result->image = el_class->image;
6434 result->inited = TRUE;
6435 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6436 /* Can pointers get boxed? */
6437 result->instance_size = sizeof (gpointer);
6438 result->cast_class = result->element_class = el_class;
6439 result->blittable = TRUE;
6441 result->byval_arg.type = MONO_TYPE_PTR;
6442 result->this_arg.type = result->byval_arg.type;
6443 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6444 result->this_arg.byref = TRUE;
6446 mono_class_setup_supertypes (result);
6448 mono_image_lock (image);
6449 if (image->ptr_cache) {
6451 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6452 mono_image_unlock (image);
6453 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6457 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6459 g_hash_table_insert (image->ptr_cache, el_class, result);
6460 mono_image_unlock (image);
6462 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6468 mono_fnptr_class_get (MonoMethodSignature *sig)
6471 static GHashTable *ptr_hash = NULL;
6473 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6475 mono_loader_lock ();
6478 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6480 if ((result = (MonoClass *)g_hash_table_lookup (ptr_hash, sig))) {
6481 mono_loader_unlock ();
6484 result = g_new0 (MonoClass, 1);
6486 result->parent = NULL; /* no parent for PTR types */
6487 result->name_space = "System";
6488 result->name = "MonoFNPtrFakeClass";
6490 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6492 result->image = mono_defaults.corlib; /* need to fix... */
6493 result->inited = TRUE;
6494 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6495 /* Can pointers get boxed? */
6496 result->instance_size = sizeof (gpointer);
6497 result->cast_class = result->element_class = result;
6498 result->blittable = TRUE;
6500 result->byval_arg.type = MONO_TYPE_FNPTR;
6501 result->this_arg.type = result->byval_arg.type;
6502 result->this_arg.data.method = result->byval_arg.data.method = sig;
6503 result->this_arg.byref = TRUE;
6504 result->blittable = TRUE;
6506 mono_class_setup_supertypes (result);
6508 g_hash_table_insert (ptr_hash, sig, result);
6510 mono_loader_unlock ();
6512 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6518 * mono_class_from_mono_type:
6519 * @type: describes the type to return
6521 * This returns a MonoClass for the specified MonoType, the value is never NULL.
6524 mono_class_from_mono_type (MonoType *type)
6526 switch (type->type) {
6527 case MONO_TYPE_OBJECT:
6528 return type->data.klass? type->data.klass: mono_defaults.object_class;
6529 case MONO_TYPE_VOID:
6530 return type->data.klass? type->data.klass: mono_defaults.void_class;
6531 case MONO_TYPE_BOOLEAN:
6532 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6533 case MONO_TYPE_CHAR:
6534 return type->data.klass? type->data.klass: mono_defaults.char_class;
6536 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6538 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6540 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6542 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6544 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6546 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6548 return type->data.klass? type->data.klass: mono_defaults.int_class;
6550 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6552 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6554 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6556 return type->data.klass? type->data.klass: mono_defaults.single_class;
6558 return type->data.klass? type->data.klass: mono_defaults.double_class;
6559 case MONO_TYPE_STRING:
6560 return type->data.klass? type->data.klass: mono_defaults.string_class;
6561 case MONO_TYPE_TYPEDBYREF:
6562 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6563 case MONO_TYPE_ARRAY:
6564 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6566 return mono_ptr_class_get (type->data.type);
6567 case MONO_TYPE_FNPTR:
6568 return mono_fnptr_class_get (type->data.method);
6569 case MONO_TYPE_SZARRAY:
6570 return mono_array_class_get (type->data.klass, 1);
6571 case MONO_TYPE_CLASS:
6572 case MONO_TYPE_VALUETYPE:
6573 return type->data.klass;
6574 case MONO_TYPE_GENERICINST:
6575 return mono_generic_class_get_class (type->data.generic_class);
6576 case MONO_TYPE_MVAR:
6578 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6580 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6581 g_assert_not_reached ();
6584 // Yes, this returns NULL, even if it is documented as not doing so, but there
6585 // is no way for the code to make it this far, due to the assert above.
6590 * mono_type_retrieve_from_typespec
6591 * @image: context where the image is created
6592 * @type_spec: typespec token
6593 * @context: the generic context used to evaluate generic instantiations in
6596 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6598 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6600 *did_inflate = FALSE;
6605 if (context && (context->class_inst || context->method_inst)) {
6606 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6608 if (!mono_error_ok (error)) {
6614 *did_inflate = TRUE;
6621 * mono_class_create_from_typespec
6622 * @image: context where the image is created
6623 * @type_spec: typespec token
6624 * @context: the generic context used to evaluate generic instantiations in
6627 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6630 gboolean inflated = FALSE;
6631 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6632 return_val_if_nok (error, NULL);
6633 ret = mono_class_from_mono_type (t);
6635 mono_metadata_free_type (t);
6640 * mono_bounded_array_class_get:
6641 * @element_class: element class
6642 * @rank: the dimension of the array class
6643 * @bounded: whenever the array has non-zero bounds
6645 * Returns: A class object describing the array with element type @element_type and
6649 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6653 MonoClass *parent = NULL;
6654 GSList *list, *rootlist = NULL;
6657 gboolean corlib_type = FALSE;
6659 g_assert (rank <= 255);
6662 /* bounded only matters for one-dimensional arrays */
6665 image = eclass->image;
6667 if (rank == 1 && !bounded) {
6669 * This case is very frequent not just during compilation because of calls
6670 * from mono_class_from_mono_type (), mono_array_new (),
6671 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6673 mono_os_mutex_lock (&image->szarray_cache_lock);
6674 if (!image->szarray_cache)
6675 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6676 klass = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6677 mono_os_mutex_unlock (&image->szarray_cache_lock);
6681 mono_loader_lock ();
6683 mono_loader_lock ();
6685 if (!image->array_cache)
6686 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6688 if ((rootlist = list = (GSList *)g_hash_table_lookup (image->array_cache, eclass))) {
6689 for (; list; list = list->next) {
6690 klass = (MonoClass *)list->data;
6691 if ((klass->rank == rank) && (klass->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6692 mono_loader_unlock ();
6699 /* for the building corlib use System.Array from it */
6700 if (image->assembly && assembly_is_dynamic (image->assembly) && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6701 parent = mono_class_load_from_name (image, "System", "Array");
6704 parent = mono_defaults.array_class;
6705 if (!parent->inited)
6706 mono_class_init (parent);
6709 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6711 klass->image = image;
6712 klass->name_space = eclass->name_space;
6713 nsize = strlen (eclass->name);
6714 name = (char *)g_malloc (nsize + 2 + rank + 1);
6715 memcpy (name, eclass->name, nsize);
6718 memset (name + nsize + 1, ',', rank - 1);
6720 name [nsize + rank] = '*';
6721 name [nsize + rank + bounded] = ']';
6722 name [nsize + rank + bounded + 1] = 0;
6723 klass->name = mono_image_strdup (image, name);
6726 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6728 classes_size += sizeof (MonoClass);
6730 klass->type_token = 0;
6731 /* all arrays are marked serializable and sealed, bug #42779 */
6732 klass->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6733 klass->parent = parent;
6734 klass->instance_size = mono_class_instance_size (klass->parent);
6736 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6737 /*Arrays of those two types are invalid.*/
6738 mono_class_set_failure (klass, MONO_EXCEPTION_INVALID_PROGRAM, NULL);
6739 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6740 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6741 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6742 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6744 /* element_size -1 is ok as this is not an instantitable type*/
6745 klass->sizes.element_size = -1;
6747 klass->sizes.element_size = mono_class_array_element_size (eclass);
6749 mono_class_setup_supertypes (klass);
6751 if (eclass->generic_class)
6752 mono_class_init (eclass);
6753 if (!eclass->size_inited)
6754 mono_class_setup_fields (eclass);
6755 if (mono_class_has_failure (eclass)) /*FIXME we fail the array type, but we have to let other fields be set.*/
6756 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
6758 klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6762 if (eclass->enumtype)
6763 klass->cast_class = eclass->element_class;
6765 klass->cast_class = eclass;
6767 switch (klass->cast_class->byval_arg.type) {
6769 klass->cast_class = mono_defaults.byte_class;
6772 klass->cast_class = mono_defaults.int16_class;
6775 #if SIZEOF_VOID_P == 4
6779 klass->cast_class = mono_defaults.int32_class;
6782 #if SIZEOF_VOID_P == 8
6786 klass->cast_class = mono_defaults.int64_class;
6792 klass->element_class = eclass;
6794 if ((rank > 1) || bounded) {
6795 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6796 klass->byval_arg.type = MONO_TYPE_ARRAY;
6797 klass->byval_arg.data.array = at;
6798 at->eklass = eclass;
6800 /* FIXME: complete.... */
6802 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6803 klass->byval_arg.data.klass = eclass;
6805 klass->this_arg = klass->byval_arg;
6806 klass->this_arg.byref = 1;
6811 klass->generic_container = eclass->generic_container;
6813 if (rank == 1 && !bounded) {
6814 MonoClass *prev_class;
6816 mono_os_mutex_lock (&image->szarray_cache_lock);
6817 prev_class = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6819 /* Someone got in before us */
6822 g_hash_table_insert (image->szarray_cache, eclass, klass);
6823 mono_os_mutex_unlock (&image->szarray_cache_lock);
6825 list = g_slist_append (rootlist, klass);
6826 g_hash_table_insert (image->array_cache, eclass, list);
6829 mono_loader_unlock ();
6831 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6837 * mono_array_class_get:
6838 * @element_class: element class
6839 * @rank: the dimension of the array class
6841 * Returns: A class object describing the array with element type @element_type and
6845 mono_array_class_get (MonoClass *eclass, guint32 rank)
6847 return mono_bounded_array_class_get (eclass, rank, FALSE);
6851 * mono_class_instance_size:
6854 * Use to get the size of a class in bytes.
6856 * Returns: The size of an object instance
6859 mono_class_instance_size (MonoClass *klass)
6861 if (!klass->size_inited)
6862 mono_class_init (klass);
6864 return klass->instance_size;
6868 * mono_class_min_align:
6871 * Use to get the computed minimum alignment requirements for the specified class.
6873 * Returns: minimm alignment requirements
6876 mono_class_min_align (MonoClass *klass)
6878 if (!klass->size_inited)
6879 mono_class_init (klass);
6881 return klass->min_align;
6885 * mono_class_value_size:
6888 * This function is used for value types, and return the
6889 * space and the alignment to store that kind of value object.
6891 * Returns: the size of a value of kind @klass
6894 mono_class_value_size (MonoClass *klass, guint32 *align)
6898 /* fixme: check disable, because we still have external revereces to
6899 * mscorlib and Dummy Objects
6901 /*g_assert (klass->valuetype);*/
6903 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6906 *align = klass->min_align;
6912 * mono_class_data_size:
6915 * Returns: The size of the static class data
6918 mono_class_data_size (MonoClass *klass)
6921 mono_class_init (klass);
6922 /* This can happen with dynamically created types */
6923 if (!klass->fields_inited)
6924 mono_class_setup_fields_locking (klass);
6926 /* in arrays, sizes.class_size is unioned with element_size
6927 * and arrays have no static fields
6931 return klass->sizes.class_size;
6935 * Auxiliary routine to mono_class_get_field
6937 * Takes a field index instead of a field token.
6939 static MonoClassField *
6940 mono_class_get_field_idx (MonoClass *klass, int idx)
6942 mono_class_setup_fields_locking (klass);
6943 if (mono_class_has_failure (klass))
6947 if (klass->image->uncompressed_metadata) {
6949 * klass->field.first points to the FieldPtr table, while idx points into the
6950 * Field table, so we have to do a search.
6952 /*FIXME this is broken for types with multiple fields with the same name.*/
6953 const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6956 for (i = 0; i < klass->field.count; ++i)
6957 if (mono_field_get_name (&klass->fields [i]) == name)
6958 return &klass->fields [i];
6959 g_assert_not_reached ();
6961 if (klass->field.count) {
6962 if ((idx >= klass->field.first) && (idx < klass->field.first + klass->field.count)){
6963 return &klass->fields [idx - klass->field.first];
6967 klass = klass->parent;
6973 * mono_class_get_field:
6974 * @class: the class to lookup the field.
6975 * @field_token: the field token
6977 * Returns: A MonoClassField representing the type and offset of
6978 * the field, or a NULL value if the field does not belong to this
6982 mono_class_get_field (MonoClass *klass, guint32 field_token)
6984 int idx = mono_metadata_token_index (field_token);
6986 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6988 return mono_class_get_field_idx (klass, idx - 1);
6992 * mono_class_get_field_from_name:
6993 * @klass: the class to lookup the field.
6994 * @name: the field name
6996 * Search the class @klass and it's parents for a field with the name @name.
6998 * Returns: The MonoClassField pointer of the named field or NULL
7001 mono_class_get_field_from_name (MonoClass *klass, const char *name)
7003 return mono_class_get_field_from_name_full (klass, name, NULL);
7007 * mono_class_get_field_from_name_full:
7008 * @klass: the class to lookup the field.
7009 * @name: the field name
7010 * @type: the type of the fields. This optional.
7012 * Search the class @klass and it's parents for a field with the name @name and type @type.
7014 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
7015 * of its generic type definition.
7017 * Returns: The MonoClassField pointer of the named field or NULL
7020 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
7024 mono_class_setup_fields_locking (klass);
7025 if (mono_class_has_failure (klass))
7029 for (i = 0; i < klass->field.count; ++i) {
7030 MonoClassField *field = &klass->fields [i];
7032 if (strcmp (name, mono_field_get_name (field)) != 0)
7036 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
7037 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
7042 klass = klass->parent;
7048 * mono_class_get_field_token:
7049 * @field: the field we need the token of
7051 * Get the token of a field. Note that the tokesn is only valid for the image
7052 * the field was loaded from. Don't use this function for fields in dynamic types.
7054 * Returns: The token representing the field in the image it was loaded from.
7057 mono_class_get_field_token (MonoClassField *field)
7059 MonoClass *klass = field->parent;
7062 mono_class_setup_fields_locking (klass);
7067 for (i = 0; i < klass->field.count; ++i) {
7068 if (&klass->fields [i] == field) {
7069 int idx = klass->field.first + i + 1;
7071 if (klass->image->uncompressed_metadata)
7072 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
7073 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
7076 klass = klass->parent;
7079 g_assert_not_reached ();
7084 mono_field_get_index (MonoClassField *field)
7086 int index = field - field->parent->fields;
7088 g_assert (index >= 0 && index < field->parent->field.count);
7094 * mono_class_get_field_default_value:
7096 * Return the default value of the field as a pointer into the metadata blob.
7099 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
7102 guint32 constant_cols [MONO_CONSTANT_SIZE];
7104 MonoClass *klass = field->parent;
7106 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7108 if (!klass->ext || !klass->ext->field_def_values) {
7109 MonoFieldDefaultValue *def_values;
7111 mono_class_alloc_ext (klass);
7113 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
7115 mono_image_lock (klass->image);
7116 mono_memory_barrier ();
7117 if (!klass->ext->field_def_values)
7118 klass->ext->field_def_values = def_values;
7119 mono_image_unlock (klass->image);
7122 field_index = mono_field_get_index (field);
7124 if (!klass->ext->field_def_values [field_index].data) {
7125 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7129 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7131 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7132 klass->ext->field_def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7133 klass->ext->field_def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7136 *def_type = klass->ext->field_def_values [field_index].def_type;
7137 return klass->ext->field_def_values [field_index].data;
7141 mono_property_get_index (MonoProperty *prop)
7143 int index = prop - prop->parent->ext->properties;
7145 g_assert (index >= 0 && index < prop->parent->ext->property.count);
7151 * mono_class_get_property_default_value:
7153 * Return the default value of the field as a pointer into the metadata blob.
7156 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7159 guint32 constant_cols [MONO_CONSTANT_SIZE];
7160 MonoClass *klass = property->parent;
7162 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7164 * We don't cache here because it is not used by C# so it's quite rare, but
7165 * we still do the lookup in klass->ext because that is where the data
7166 * is stored for dynamic assemblies.
7169 if (image_is_dynamic (klass->image)) {
7170 int prop_index = mono_property_get_index (property);
7171 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
7172 *def_type = klass->ext->prop_def_values [prop_index].def_type;
7173 return klass->ext->prop_def_values [prop_index].data;
7177 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7181 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7182 *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7183 return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7187 mono_class_get_event_token (MonoEvent *event)
7189 MonoClass *klass = event->parent;
7194 for (i = 0; i < klass->ext->event.count; ++i) {
7195 if (&klass->ext->events [i] == event)
7196 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
7199 klass = klass->parent;
7202 g_assert_not_reached ();
7207 * mono_class_get_property_from_name:
7209 * @name: name of the property to lookup in the specified class
7211 * Use this method to lookup a property in a class
7212 * Returns: the MonoProperty with the given name, or NULL if the property
7213 * does not exist on the @klass.
7216 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7220 gpointer iter = NULL;
7221 while ((p = mono_class_get_properties (klass, &iter))) {
7222 if (! strcmp (name, p->name))
7225 klass = klass->parent;
7231 * mono_class_get_property_token:
7232 * @prop: MonoProperty to query
7234 * Returns: The ECMA token for the specified property.
7237 mono_class_get_property_token (MonoProperty *prop)
7239 MonoClass *klass = prop->parent;
7243 gpointer iter = NULL;
7244 while ((p = mono_class_get_properties (klass, &iter))) {
7245 if (&klass->ext->properties [i] == prop)
7246 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
7250 klass = klass->parent;
7253 g_assert_not_reached ();
7258 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7260 const char *name, *nspace;
7261 if (image_is_dynamic (image))
7262 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7264 switch (type_token & 0xff000000){
7265 case MONO_TOKEN_TYPE_DEF: {
7266 guint32 cols [MONO_TYPEDEF_SIZE];
7267 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7268 guint tidx = mono_metadata_token_index (type_token);
7270 if (tidx > tt->rows)
7271 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7273 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7274 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7275 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7276 if (strlen (nspace) == 0)
7277 return g_strdup_printf ("%s", name);
7279 return g_strdup_printf ("%s.%s", nspace, name);
7282 case MONO_TOKEN_TYPE_REF: {
7284 guint32 cols [MONO_TYPEREF_SIZE];
7285 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7286 guint tidx = mono_metadata_token_index (type_token);
7289 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7291 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7292 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7293 mono_error_cleanup (&error);
7297 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7298 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7299 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7300 if (strlen (nspace) == 0)
7301 return g_strdup_printf ("%s", name);
7303 return g_strdup_printf ("%s.%s", nspace, name);
7306 case MONO_TOKEN_TYPE_SPEC:
7307 return g_strdup_printf ("Typespec 0x%08x", type_token);
7309 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7314 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7316 if (image_is_dynamic (image))
7317 return g_strdup_printf ("DynamicAssembly %s", image->name);
7319 switch (type_token & 0xff000000){
7320 case MONO_TOKEN_TYPE_DEF:
7321 if (image->assembly)
7322 return mono_stringify_assembly_name (&image->assembly->aname);
7323 else if (image->assembly_name)
7324 return g_strdup (image->assembly_name);
7325 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7326 case MONO_TOKEN_TYPE_REF: {
7328 MonoAssemblyName aname;
7329 guint32 cols [MONO_TYPEREF_SIZE];
7330 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7331 guint32 idx = mono_metadata_token_index (type_token);
7334 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7336 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7337 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7338 mono_error_cleanup (&error);
7341 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7343 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7344 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7345 case MONO_RESOLUTION_SCOPE_MODULE:
7347 return g_strdup ("");
7348 case MONO_RESOLUTION_SCOPE_MODULEREF:
7350 return g_strdup ("");
7351 case MONO_RESOLUTION_SCOPE_TYPEREF:
7353 return g_strdup ("");
7354 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7355 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7356 return mono_stringify_assembly_name (&aname);
7358 g_assert_not_reached ();
7362 case MONO_TOKEN_TYPE_SPEC:
7364 return g_strdup ("");
7366 g_assert_not_reached ();
7373 * mono_class_get_full:
7374 * @image: the image where the class resides
7375 * @type_token: the token for the class
7376 * @context: the generic context used to evaluate generic instantiations in
7377 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7379 * Returns: The MonoClass that represents @type_token in @image
7382 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7386 klass = mono_class_get_checked (image, type_token, &error);
7388 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7389 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7391 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7397 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7401 mono_error_init (error);
7402 klass = mono_class_get_checked (image, type_token, error);
7404 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7405 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7410 * mono_class_get_checked:
7411 * @image: the image where the class resides
7412 * @type_token: the token for the class
7413 * @error: error object to return any error
7415 * Returns: The MonoClass that represents @type_token in @image, or NULL on error.
7418 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7420 MonoClass *klass = NULL;
7422 mono_error_init (error);
7424 if (image_is_dynamic (image)) {
7425 int table = mono_metadata_token_table (type_token);
7427 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7428 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7431 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
7435 switch (type_token & 0xff000000){
7436 case MONO_TOKEN_TYPE_DEF:
7437 klass = mono_class_create_from_typedef (image, type_token, error);
7439 case MONO_TOKEN_TYPE_REF:
7440 klass = mono_class_from_typeref_checked (image, type_token, error);
7442 case MONO_TOKEN_TYPE_SPEC:
7443 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7446 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7450 /* Generic case, should be avoided for when a better error is possible. */
7451 if (!klass && mono_error_ok (error)) {
7452 char *name = mono_class_name_from_token (image, type_token);
7453 char *assembly = mono_assembly_name_from_token (image, type_token);
7454 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7462 * mono_type_get_checked:
7463 * @image: the image where the type resides
7464 * @type_token: the token for the type
7465 * @context: the generic context used to evaluate generic instantiations in
7466 * @error: Error handling context
7468 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7470 * Returns: The MonoType that represents @type_token in @image
7473 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7475 MonoType *type = NULL;
7476 gboolean inflated = FALSE;
7478 mono_error_init (error);
7480 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7481 if (image_is_dynamic (image)) {
7482 MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
7483 return_val_if_nok (error, NULL);
7484 return mono_class_get_type (klass);
7487 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7488 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7495 return mono_class_get_type (klass);
7498 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7505 MonoType *tmp = type;
7506 type = mono_class_get_type (mono_class_from_mono_type (type));
7507 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7508 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7509 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7511 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7513 if (type->type != tmp->type)
7516 mono_metadata_free_type (tmp);
7523 * @image: image where the class token will be looked up.
7524 * @type_token: a type token from the image
7526 * Returns the MonoClass with the given @type_token on the @image
7529 mono_class_get (MonoImage *image, guint32 type_token)
7531 return mono_class_get_full (image, type_token, NULL);
7535 * mono_image_init_name_cache:
7537 * Initializes the class name cache stored in image->name_cache.
7539 * LOCKING: Acquires the corresponding image lock.
7542 mono_image_init_name_cache (MonoImage *image)
7544 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7545 guint32 cols [MONO_TYPEDEF_SIZE];
7548 guint32 i, visib, nspace_index;
7549 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7551 if (image->name_cache)
7554 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7556 if (image_is_dynamic (image)) {
7557 mono_image_lock (image);
7558 if (image->name_cache) {
7559 /* Somebody initialized it before us */
7560 g_hash_table_destroy (the_name_cache);
7562 mono_atomic_store_release (&image->name_cache, the_name_cache);
7564 mono_image_unlock (image);
7568 /* Temporary hash table to avoid lookups in the nspace_table */
7569 name_cache2 = g_hash_table_new (NULL, NULL);
7571 for (i = 1; i <= t->rows; ++i) {
7572 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7573 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7575 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7576 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7578 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7580 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7581 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7583 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7584 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7585 if (!nspace_table) {
7586 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7587 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7588 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7591 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7594 /* Load type names from EXPORTEDTYPES table */
7596 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7597 guint32 cols [MONO_EXP_TYPE_SIZE];
7600 for (i = 0; i < t->rows; ++i) {
7601 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7603 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7604 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7608 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7609 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7611 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7612 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7613 if (!nspace_table) {
7614 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7615 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7616 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7619 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7623 g_hash_table_destroy (name_cache2);
7625 mono_image_lock (image);
7626 if (image->name_cache) {
7627 /* Somebody initialized it before us */
7628 g_hash_table_destroy (the_name_cache);
7630 mono_atomic_store_release (&image->name_cache, the_name_cache);
7632 mono_image_unlock (image);
7635 /*FIXME Only dynamic assemblies should allow this operation.*/
7637 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7638 const char *name, guint32 index)
7640 GHashTable *nspace_table;
7641 GHashTable *name_cache;
7644 mono_image_init_name_cache (image);
7645 mono_image_lock (image);
7647 name_cache = image->name_cache;
7648 if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7649 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7650 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7653 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7654 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7656 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7658 mono_image_unlock (image);
7667 find_nocase (gpointer key, gpointer value, gpointer user_data)
7669 char *name = (char*)key;
7670 FindUserData *data = (FindUserData*)user_data;
7672 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7673 data->value = value;
7677 * mono_class_from_name_case:
7678 * @image: The MonoImage where the type is looked up in
7679 * @name_space: the type namespace
7680 * @name: the type short name.
7681 * @deprecated: use the mono_class_from_name_case_checked variant instead.
7683 * Obtains a MonoClass with a given namespace and a given name which
7684 * is located in the given MonoImage. The namespace and name
7685 * lookups are case insensitive.
7688 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7691 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7692 mono_error_cleanup (&error);
7698 * mono_class_from_name_case:
7699 * @image: The MonoImage where the type is looked up in
7700 * @name_space: the type namespace
7701 * @name: the type short name.
7704 * Obtains a MonoClass with a given namespace and a given name which
7705 * is located in the given MonoImage. The namespace and name
7706 * lookups are case insensitive.
7708 * Returns: The MonoClass if the given namespace and name were found, or NULL if it
7709 * was not found. The @error object will contain information about the problem
7713 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7715 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7716 guint32 cols [MONO_TYPEDEF_SIZE];
7721 mono_error_init (error);
7723 if (image_is_dynamic (image)) {
7725 FindUserData user_data;
7727 mono_image_init_name_cache (image);
7728 mono_image_lock (image);
7730 user_data.key = name_space;
7731 user_data.value = NULL;
7732 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7734 if (user_data.value) {
7735 GHashTable *nspace_table = (GHashTable*)user_data.value;
7737 user_data.key = name;
7738 user_data.value = NULL;
7740 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7742 if (user_data.value)
7743 token = GPOINTER_TO_UINT (user_data.value);
7746 mono_image_unlock (image);
7749 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7755 /* add a cache if needed */
7756 for (i = 1; i <= t->rows; ++i) {
7757 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7758 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7760 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7761 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7763 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7765 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7766 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7767 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7768 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7774 return_nested_in (MonoClass *klass, char *nested)
7777 char *s = strchr (nested, '/');
7778 gpointer iter = NULL;
7785 while ((found = mono_class_get_nested_types (klass, &iter))) {
7786 if (strcmp (found->name, nested) == 0) {
7788 return return_nested_in (found, s);
7796 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7798 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7799 MonoImage *file_image;
7803 mono_error_init (error);
7806 * The EXPORTEDTYPES table only contains public types, so have to search the
7808 * Note: image->modules contains the contents of the MODULEREF table, while
7809 * the real module list is in the FILE table.
7811 for (i = 0; i < file_table->rows; i++) {
7812 guint32 cols [MONO_FILE_SIZE];
7813 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7814 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7817 file_image = mono_image_load_file_for_image (image, i + 1);
7819 klass = mono_class_from_name_checked (file_image, name_space, name, error);
7820 if (klass || !is_ok (error))
7829 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7831 GHashTable *nspace_table;
7832 MonoImage *loaded_image;
7839 mono_error_init (error);
7841 // Checking visited images avoids stack overflows when cyclic references exist.
7842 if (g_hash_table_lookup (visited_images, image))
7845 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7847 if ((nested = strchr (name, '/'))) {
7848 int pos = nested - name;
7849 int len = strlen (name);
7852 memcpy (buf, name, len + 1);
7854 nested = buf + pos + 1;
7858 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7859 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7860 gboolean res = get_class_from_name (image, name_space, name, &klass);
7863 klass = search_modules (image, name_space, name, error);
7868 return klass ? return_nested_in (klass, nested) : NULL;
7874 mono_image_init_name_cache (image);
7875 mono_image_lock (image);
7877 nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7880 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7882 mono_image_unlock (image);
7884 if (!token && image_is_dynamic (image) && image->modules) {
7885 /* Search modules as well */
7886 for (i = 0; i < image->module_count; ++i) {
7887 MonoImage *module = image->modules [i];
7889 klass = mono_class_from_name_checked (module, name_space, name, error);
7890 if (klass || !is_ok (error))
7896 klass = search_modules (image, name_space, name, error);
7897 if (klass || !is_ok (error))
7902 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7903 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7904 guint32 cols [MONO_EXP_TYPE_SIZE];
7907 idx = mono_metadata_token_index (token);
7909 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7911 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7912 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7913 loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
7916 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7918 return klass ? return_nested_in (klass, nested) : NULL;
7920 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7921 guint32 assembly_idx;
7923 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7925 mono_assembly_load_reference (image, assembly_idx - 1);
7926 g_assert (image->references [assembly_idx - 1]);
7927 if (image->references [assembly_idx - 1] == (gpointer)-1)
7929 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
7931 return klass ? return_nested_in (klass, nested) : NULL;
7934 g_assert_not_reached ();
7938 token = MONO_TOKEN_TYPE_DEF | token;
7940 klass = mono_class_get_checked (image, token, error);
7942 return return_nested_in (klass, nested);
7947 * mono_class_from_name_checked:
7948 * @image: The MonoImage where the type is looked up in
7949 * @name_space: the type namespace
7950 * @name: the type short name.
7952 * Obtains a MonoClass with a given namespace and a given name which
7953 * is located in the given MonoImage.
7955 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
7956 * set if the class was not found or it will return NULL and set the error if there was a loading error.
7959 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7962 GHashTable *visited_images;
7964 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7966 klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
7968 g_hash_table_destroy (visited_images);
7974 * mono_class_from_name:
7975 * @image: The MonoImage where the type is looked up in
7976 * @name_space: the type namespace
7977 * @name: the type short name.
7979 * Obtains a MonoClass with a given namespace and a given name which
7980 * is located in the given MonoImage.
7982 * To reference nested classes, use the "/" character as a separator.
7983 * For example use "Foo/Bar" to reference the class Bar that is nested
7984 * inside Foo, like this: "class Foo { class Bar {} }".
7987 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7992 klass = mono_class_from_name_checked (image, name_space, name, &error);
7993 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
7999 * mono_class_load_from_name:
8000 * @image: The MonoImage where the type is looked up in
8001 * @name_space: the type namespace
8002 * @name: the type short name.
8004 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
8005 * This function should be used by the runtime for critical types to which there's no way to recover but crash
8006 * If they are missing. Thing of System.Object or System.String.
8009 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
8014 klass = mono_class_from_name_checked (image, name_space, name, &error);
8016 g_error ("Runtime critical type %s.%s not found", name_space, name);
8017 if (!mono_error_ok (&error))
8018 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8023 * mono_class_try_load_from_name:
8024 * @image: The MonoImage where the type is looked up in
8025 * @name_space: the type namespace
8026 * @name: the type short name.
8028 * This function tries to load a type, returning the class was found or NULL otherwise.
8029 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
8031 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
8032 * a type that we would otherwise assume to be available but was not due some error.
8036 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
8041 klass = mono_class_from_name_checked (image, name_space, name, &error);
8042 if (!mono_error_ok (&error))
8043 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8049 * mono_class_is_subclass_of:
8050 * @klass: class to probe if it is a subclass of another one
8051 * @klassc: the class we suspect is the base class
8052 * @check_interfaces: whether we should perform interface checks
8054 * This method determines whether @klass is a subclass of @klassc.
8056 * If the @check_interfaces flag is set, then if @klassc is an interface
8057 * this method return TRUE if the @klass implements the interface or
8058 * if @klass is an interface, if one of its base classes is @klass.
8060 * If @check_interfaces is false then, then if @klass is not an interface
8061 * then it returns TRUE if the @klass is a subclass of @klassc.
8063 * if @klass is an interface and @klassc is System.Object, then this function
8068 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
8069 gboolean check_interfaces)
8071 /* FIXME test for interfaces with variant generic arguments */
8072 mono_class_init (klass);
8073 mono_class_init (klassc);
8075 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
8076 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
8078 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
8081 for (i = 0; i < klass->interface_count; i ++) {
8082 MonoClass *ic = klass->interfaces [i];
8087 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
8092 * MS.NET thinks interfaces are a subclass of Object, so we think it as
8095 if (klassc == mono_defaults.object_class)
8102 mono_type_is_generic_argument (MonoType *type)
8104 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
8108 mono_class_has_variant_generic_params (MonoClass *klass)
8111 MonoGenericContainer *container;
8113 if (!klass->generic_class)
8116 container = klass->generic_class->container_class->generic_container;
8118 for (i = 0; i < container->type_argc; ++i)
8119 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8126 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8128 if (target == candidate)
8131 if (check_for_reference_conv &&
8132 mono_type_is_generic_argument (&target->byval_arg) &&
8133 mono_type_is_generic_argument (&candidate->byval_arg)) {
8134 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8135 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8137 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8140 if (!mono_class_is_assignable_from (target, candidate))
8146 * @container the generic container from the GTD
8147 * @klass: the class to be assigned to
8148 * @oklass: the source class
8150 * Both @klass and @oklass must be instances of the same generic interface.
8152 * Returns: TRUE if @klass can be assigned to a @klass variable
8155 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8158 MonoType **klass_argv, **oklass_argv;
8159 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8160 MonoGenericContainer *container = klass_gtd->generic_container;
8162 if (klass == oklass)
8165 /*Viable candidates are instances of the same generic interface*/
8166 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8169 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8170 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8172 for (j = 0; j < container->type_argc; ++j) {
8173 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8174 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8176 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8180 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8181 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8183 if (param1_class != param2_class) {
8184 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8185 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8187 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8188 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8198 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8200 MonoGenericParam *gparam, *ogparam;
8201 MonoGenericParamInfo *tinfo, *cinfo;
8202 MonoClass **candidate_class;
8203 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8206 if (target == candidate)
8208 if (target->byval_arg.type != candidate->byval_arg.type)
8211 gparam = target->byval_arg.data.generic_param;
8212 ogparam = candidate->byval_arg.data.generic_param;
8213 tinfo = mono_generic_param_info (gparam);
8214 cinfo = mono_generic_param_info (ogparam);
8216 class_constraint_satisfied = FALSE;
8217 valuetype_constraint_satisfied = FALSE;
8219 /*candidate must have a super set of target's special constraints*/
8220 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8221 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8223 if (cinfo->constraints) {
8224 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8225 MonoClass *cc = *candidate_class;
8227 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8228 class_constraint_satisfied = TRUE;
8229 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8230 valuetype_constraint_satisfied = TRUE;
8233 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8234 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8236 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8238 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8240 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8241 valuetype_constraint_satisfied)) {
8246 /*candidate type constraints must be a superset of target's*/
8247 if (tinfo->constraints) {
8248 MonoClass **target_class;
8249 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8250 MonoClass *tc = *target_class;
8253 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8254 * check it's constraints since it satisfy the constraint by itself.
8256 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8259 if (!cinfo->constraints)
8262 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8263 MonoClass *cc = *candidate_class;
8265 if (mono_class_is_assignable_from (tc, cc))
8269 * This happens when we have the following:
8271 * Bar<K> where K : IFace
8272 * Foo<T, U> where T : U where U : IFace
8274 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8277 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8278 if (mono_gparam_is_assignable_from (target, cc))
8282 if (!*candidate_class)
8287 /*candidate itself must have a constraint that satisfy target*/
8288 if (cinfo->constraints) {
8289 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8290 MonoClass *cc = *candidate_class;
8291 if (mono_class_is_assignable_from (target, cc))
8299 * mono_class_is_assignable_from:
8300 * @klass: the class to be assigned to
8301 * @oklass: the source class
8303 * Returns: TRUE if an instance of object oklass can be assigned to an
8304 * instance of object @klass
8307 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8310 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8312 mono_class_init (klass);
8314 if (!oklass->inited)
8315 mono_class_init (oklass);
8317 if (mono_class_has_failure (klass) || mono_class_has_failure (oklass))
8320 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8321 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8323 return mono_gparam_is_assignable_from (klass, oklass);
8326 if (MONO_CLASS_IS_INTERFACE (klass)) {
8327 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8328 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8329 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8333 for (i = 0; constraints [i]; ++i) {
8334 if (mono_class_is_assignable_from (klass, constraints [i]))
8342 /* interface_offsets might not be set for dynamic classes */
8343 if (oklass->ref_info_handle && !oklass->interface_bitmap) {
8345 * oklass might be a generic type parameter but they have
8346 * interface_offsets set.
8348 gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8349 if (!is_ok (&error)) {
8350 mono_error_cleanup (&error);
8355 if (!oklass->interface_bitmap)
8356 /* Happens with generic instances of not-yet created dynamic types */
8358 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8361 if (mono_class_has_variant_generic_params (klass)) {
8363 mono_class_setup_interfaces (oklass, &error);
8364 if (!mono_error_ok (&error)) {
8365 mono_error_cleanup (&error);
8369 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8370 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8371 MonoClass *iface = oklass->interfaces_packed [i];
8373 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8378 } else if (klass->delegate) {
8379 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8381 }else if (klass->rank) {
8382 MonoClass *eclass, *eoclass;
8384 if (oklass->rank != klass->rank)
8387 /* vectors vs. one dimensional arrays */
8388 if (oklass->byval_arg.type != klass->byval_arg.type)
8391 eclass = klass->cast_class;
8392 eoclass = oklass->cast_class;
8395 * a is b does not imply a[] is b[] when a is a valuetype, and
8396 * b is a reference type.
8399 if (eoclass->valuetype) {
8400 if ((eclass == mono_defaults.enum_class) ||
8401 (eclass == mono_defaults.enum_class->parent) ||
8402 (eclass == mono_defaults.object_class))
8406 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8407 } else if (mono_class_is_nullable (klass)) {
8408 if (mono_class_is_nullable (oklass))
8409 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8411 return mono_class_is_assignable_from (klass->cast_class, oklass);
8412 } else if (klass == mono_defaults.object_class)
8415 return mono_class_has_parent (oklass, klass);
8418 /*Check if @oklass is variant compatible with @klass.*/
8420 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8423 MonoType **klass_argv, **oklass_argv;
8424 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8425 MonoGenericContainer *container = klass_gtd->generic_container;
8427 /*Viable candidates are instances of the same generic interface*/
8428 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8431 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8432 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8434 for (j = 0; j < container->type_argc; ++j) {
8435 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8436 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8438 if (param1_class->valuetype != param2_class->valuetype)
8442 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8443 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8445 if (param1_class != param2_class) {
8446 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8447 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8449 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8450 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8458 /*Check if @candidate implements the interface @target*/
8460 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8464 gboolean is_variant = mono_class_has_variant_generic_params (target);
8466 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8467 if (mono_class_is_variant_compatible_slow (target, candidate))
8472 if (candidate == target)
8475 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8476 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8477 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (candidate);
8479 if (tb && tb->interfaces) {
8480 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8481 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8482 MonoClass *iface_class;
8484 /* we can't realize the type here since it can do pretty much anything. */
8487 iface_class = mono_class_from_mono_type (iface->type);
8488 if (iface_class == target)
8490 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8492 if (mono_class_implement_interface_slow (target, iface_class))
8497 /*setup_interfaces don't mono_class_init anything*/
8498 /*FIXME this doesn't handle primitive type arrays.
8499 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8500 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8502 mono_class_setup_interfaces (candidate, &error);
8503 if (!mono_error_ok (&error)) {
8504 mono_error_cleanup (&error);
8508 for (i = 0; i < candidate->interface_count; ++i) {
8509 if (candidate->interfaces [i] == target)
8512 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8515 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8519 candidate = candidate->parent;
8520 } while (candidate);
8526 * Check if @oklass can be assigned to @klass.
8527 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8530 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8532 if (candidate == target)
8534 if (target == mono_defaults.object_class)
8537 if (mono_class_has_parent (candidate, target))
8540 /*If target is not an interface there is no need to check them.*/
8541 if (MONO_CLASS_IS_INTERFACE (target))
8542 return mono_class_implement_interface_slow (target, candidate);
8544 if (target->delegate && mono_class_has_variant_generic_params (target))
8545 return mono_class_is_variant_compatible (target, candidate, FALSE);
8548 MonoClass *eclass, *eoclass;
8550 if (target->rank != candidate->rank)
8553 /* vectors vs. one dimensional arrays */
8554 if (target->byval_arg.type != candidate->byval_arg.type)
8557 eclass = target->cast_class;
8558 eoclass = candidate->cast_class;
8561 * a is b does not imply a[] is b[] when a is a valuetype, and
8562 * b is a reference type.
8565 if (eoclass->valuetype) {
8566 if ((eclass == mono_defaults.enum_class) ||
8567 (eclass == mono_defaults.enum_class->parent) ||
8568 (eclass == mono_defaults.object_class))
8572 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8574 /*FIXME properly handle nullables */
8575 /*FIXME properly handle (M)VAR */
8580 * mono_class_get_cctor:
8581 * @klass: A MonoClass pointer
8583 * Returns: The static constructor of @klass if it exists, NULL otherwise.
8586 mono_class_get_cctor (MonoClass *klass)
8588 MonoCachedClassInfo cached_info;
8590 if (image_is_dynamic (klass->image)) {
8592 * has_cctor is not set for these classes because mono_class_init () is
8595 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8598 if (!klass->has_cctor)
8601 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8603 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8604 if (!mono_error_ok (&error))
8605 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8609 if (klass->generic_class && !klass->methods)
8610 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8612 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8616 * mono_class_get_finalizer:
8617 * @klass: The MonoClass pointer
8619 * Returns: The finalizer method of @klass if it exists, NULL otherwise.
8622 mono_class_get_finalizer (MonoClass *klass)
8624 MonoCachedClassInfo cached_info;
8627 mono_class_init (klass);
8628 if (!mono_class_has_finalizer (klass))
8631 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8633 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8634 if (!mono_error_ok (&error))
8635 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8638 mono_class_setup_vtable (klass);
8639 return klass->vtable [finalize_slot];
8644 * mono_class_needs_cctor_run:
8645 * @klass: the MonoClass pointer
8646 * @caller: a MonoMethod describing the caller
8648 * Determines whenever the class has a static constructor and whenever it
8649 * needs to be called when executing CALLER.
8652 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8656 method = mono_class_get_cctor (klass);
8658 return (method == caller) ? FALSE : TRUE;
8664 * mono_class_array_element_size:
8667 * Returns: The number of bytes an element of type @klass
8668 * uses when stored into an array.
8671 mono_class_array_element_size (MonoClass *klass)
8673 MonoType *type = &klass->byval_arg;
8676 switch (type->type) {
8679 case MONO_TYPE_BOOLEAN:
8683 case MONO_TYPE_CHAR:
8692 case MONO_TYPE_CLASS:
8693 case MONO_TYPE_STRING:
8694 case MONO_TYPE_OBJECT:
8695 case MONO_TYPE_SZARRAY:
8696 case MONO_TYPE_ARRAY:
8697 return sizeof (gpointer);
8702 case MONO_TYPE_VALUETYPE:
8703 if (type->data.klass->enumtype) {
8704 type = mono_class_enum_basetype (type->data.klass);
8705 klass = klass->element_class;
8708 return mono_class_instance_size (klass) - sizeof (MonoObject);
8709 case MONO_TYPE_GENERICINST:
8710 type = &type->data.generic_class->container_class->byval_arg;
8713 case MONO_TYPE_MVAR: {
8716 return mono_type_size (type, &align);
8718 case MONO_TYPE_VOID:
8722 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8728 * mono_array_element_size:
8729 * @ac: pointer to a #MonoArrayClass
8731 * Returns: The size of single array element.
8734 mono_array_element_size (MonoClass *ac)
8736 g_assert (ac->rank);
8737 return ac->sizes.element_size;
8741 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8742 MonoGenericContext *context)
8745 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8746 g_assert (mono_error_ok (&error));
8751 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8752 MonoGenericContext *context, MonoError *error)
8754 mono_error_init (error);
8756 if (image_is_dynamic (image)) {
8757 MonoClass *tmp_handle_class;
8758 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
8760 mono_error_assert_ok (error);
8761 g_assert (tmp_handle_class);
8763 *handle_class = tmp_handle_class;
8765 if (tmp_handle_class == mono_defaults.typehandle_class)
8766 return &((MonoClass*)obj)->byval_arg;
8771 switch (token & 0xff000000) {
8772 case MONO_TOKEN_TYPE_DEF:
8773 case MONO_TOKEN_TYPE_REF:
8774 case MONO_TOKEN_TYPE_SPEC: {
8777 *handle_class = mono_defaults.typehandle_class;
8778 type = mono_type_get_checked (image, token, context, error);
8782 mono_class_init (mono_class_from_mono_type (type));
8783 /* We return a MonoType* as handle */
8786 case MONO_TOKEN_FIELD_DEF: {
8788 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8790 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8794 *handle_class = mono_defaults.fieldhandle_class;
8795 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8799 mono_class_init (klass);
8800 return mono_class_get_field (klass, token);
8802 case MONO_TOKEN_METHOD_DEF:
8803 case MONO_TOKEN_METHOD_SPEC: {
8805 meth = mono_get_method_checked (image, token, NULL, context, error);
8807 *handle_class = mono_defaults.methodhandle_class;
8813 case MONO_TOKEN_MEMBER_REF: {
8814 guint32 cols [MONO_MEMBERREF_SIZE];
8816 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8817 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8818 mono_metadata_decode_blob_size (sig, &sig);
8819 if (*sig == 0x6) { /* it's a field */
8821 MonoClassField *field;
8822 field = mono_field_from_token_checked (image, token, &klass, context, error);
8824 *handle_class = mono_defaults.fieldhandle_class;
8828 meth = mono_get_method_checked (image, token, NULL, context, error);
8830 *handle_class = mono_defaults.methodhandle_class;
8835 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8841 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
8843 MonoClass *handle_class;
8844 mono_error_init (error);
8845 return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
8849 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
8851 return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
8854 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8857 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8859 get_cached_class_info = func;
8863 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8865 if (!get_cached_class_info)
8868 return get_cached_class_info (klass, res);
8872 mono_install_get_class_from_name (MonoGetClassFromName func)
8874 get_class_from_name = func;
8878 * mono_class_get_image:
8880 * Use this method to get the `MonoImage*` where this class came from.
8882 * Returns: The image where this class is defined.
8885 mono_class_get_image (MonoClass *klass)
8887 return klass->image;
8891 * mono_class_get_element_class:
8892 * @klass: the MonoClass to act on
8894 * Use this function to get the element class of an array.
8896 * Returns: The element class of an array.
8899 mono_class_get_element_class (MonoClass *klass)
8901 return klass->element_class;
8905 * mono_class_is_valuetype:
8906 * @klass: the MonoClass to act on
8908 * Use this method to determine if the provided `MonoClass*` represents a value type,
8909 * or a reference type.
8911 * Returns: TRUE if the MonoClass represents a ValueType, FALSE if it represents a reference type.
8914 mono_class_is_valuetype (MonoClass *klass)
8916 return klass->valuetype;
8920 * mono_class_is_enum:
8921 * @klass: the MonoClass to act on
8923 * Use this function to determine if the provided `MonoClass*` represents an enumeration.
8925 * Returns: TRUE if the MonoClass represents an enumeration.
8928 mono_class_is_enum (MonoClass *klass)
8930 return klass->enumtype;
8934 * mono_class_enum_basetype:
8935 * @klass: the MonoClass to act on
8937 * Use this function to get the underlying type for an enumeration value.
8939 * Returns: The underlying type representation for an enumeration.
8942 mono_class_enum_basetype (MonoClass *klass)
8944 if (klass->element_class == klass)
8945 /* SRE or broken types */
8948 return &klass->element_class->byval_arg;
8952 * mono_class_get_parent
8953 * @klass: the MonoClass to act on
8955 * Returns: The parent class for this class.
8958 mono_class_get_parent (MonoClass *klass)
8960 return klass->parent;
8964 * mono_class_get_nesting_type:
8965 * @klass: the MonoClass to act on
8967 * Use this function to obtain the class that the provided `MonoClass*` is nested on.
8969 * If the return is NULL, this indicates that this class is not nested.
8971 * Returns: The container type where this type is nested or NULL if this type is not a nested type.
8974 mono_class_get_nesting_type (MonoClass *klass)
8976 return klass->nested_in;
8980 * mono_class_get_rank:
8981 * @klass: the MonoClass to act on
8983 * Returns: The rank for the array (the number of dimensions).
8986 mono_class_get_rank (MonoClass *klass)
8992 * mono_class_get_flags:
8993 * @klass: the MonoClass to act on
8995 * The type flags from the TypeDef table from the metadata.
8996 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8999 * Returns: The flags from the TypeDef table.
9002 mono_class_get_flags (MonoClass *klass)
9004 return klass->flags;
9008 * mono_class_get_name
9009 * @klass: the MonoClass to act on
9011 * Returns: The name of the class.
9014 mono_class_get_name (MonoClass *klass)
9020 * mono_class_get_namespace:
9021 * @klass: the MonoClass to act on
9023 * Returns: The namespace of the class.
9026 mono_class_get_namespace (MonoClass *klass)
9028 return klass->name_space;
9032 * mono_class_get_type:
9033 * @klass: the MonoClass to act on
9035 * This method returns the internal Type representation for the class.
9037 * Returns: The MonoType from the class.
9040 mono_class_get_type (MonoClass *klass)
9042 return &klass->byval_arg;
9046 * mono_class_get_type_token:
9047 * @klass: the MonoClass to act on
9049 * This method returns type token for the class.
9051 * Returns: The type token for the class.
9054 mono_class_get_type_token (MonoClass *klass)
9056 return klass->type_token;
9060 * mono_class_get_byref_type:
9061 * @klass: the MonoClass to act on
9066 mono_class_get_byref_type (MonoClass *klass)
9068 return &klass->this_arg;
9072 * mono_class_num_fields:
9073 * @klass: the MonoClass to act on
9075 * Returns: The number of static and instance fields in the class.
9078 mono_class_num_fields (MonoClass *klass)
9080 return klass->field.count;
9084 * mono_class_num_methods:
9085 * @klass: the MonoClass to act on
9087 * Returns: The number of methods in the class.
9090 mono_class_num_methods (MonoClass *klass)
9092 return klass->method.count;
9096 * mono_class_num_properties
9097 * @klass: the MonoClass to act on
9099 * Returns: The number of properties in the class.
9102 mono_class_num_properties (MonoClass *klass)
9104 mono_class_setup_properties (klass);
9106 return klass->ext->property.count;
9110 * mono_class_num_events:
9111 * @klass: the MonoClass to act on
9113 * Returns: The number of events in the class.
9116 mono_class_num_events (MonoClass *klass)
9118 mono_class_setup_events (klass);
9120 return klass->ext->event.count;
9124 * mono_class_get_fields:
9125 * @klass: the MonoClass to act on
9127 * This routine is an iterator routine for retrieving the fields in a class.
9129 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9130 * iterate over all of the elements. When no more values are
9131 * available, the return value is NULL.
9133 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
9136 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9138 MonoClassField* field;
9142 mono_class_setup_fields_locking (klass);
9143 if (mono_class_has_failure (klass))
9145 /* start from the first */
9146 if (klass->field.count) {
9147 *iter = &klass->fields [0];
9148 return &klass->fields [0];
9154 field = (MonoClassField *)*iter;
9156 if (field < &klass->fields [klass->field.count]) {
9164 * mono_class_get_methods
9165 * @klass: the MonoClass to act on
9167 * This routine is an iterator routine for retrieving the fields in a class.
9169 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9170 * iterate over all of the elements. When no more values are
9171 * available, the return value is NULL.
9173 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
9176 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9178 MonoMethod** method;
9182 mono_class_setup_methods (klass);
9185 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9186 * FIXME we should better report this error to the caller
9188 if (!klass->methods)
9190 /* start from the first */
9191 if (klass->method.count) {
9192 *iter = &klass->methods [0];
9193 return klass->methods [0];
9199 method = (MonoMethod **)*iter;
9201 if (method < &klass->methods [klass->method.count]) {
9209 * mono_class_get_virtual_methods:
9211 * Iterate over the virtual methods of KLASS.
9213 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9216 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9218 MonoMethod** method;
9221 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9223 mono_class_setup_methods (klass);
9225 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9226 * FIXME we should better report this error to the caller
9228 if (!klass->methods)
9230 /* start from the first */
9231 method = &klass->methods [0];
9233 method = (MonoMethod **)*iter;
9236 while (method < &klass->methods [klass->method.count]) {
9237 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9241 if (method < &klass->methods [klass->method.count]) {
9248 /* Search directly in metadata to avoid calling setup_methods () */
9249 MonoMethod *res = NULL;
9255 start_index = GPOINTER_TO_UINT (*iter);
9258 for (i = start_index; i < klass->method.count; ++i) {
9261 /* klass->method.first points into the methodptr table */
9262 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
9264 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9268 if (i < klass->method.count) {
9270 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9271 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9273 /* Add 1 here so the if (*iter) check fails */
9274 *iter = GUINT_TO_POINTER (i + 1);
9283 * mono_class_get_properties:
9284 * @klass: the MonoClass to act on
9286 * This routine is an iterator routine for retrieving the properties in a class.
9288 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9289 * iterate over all of the elements. When no more values are
9290 * available, the return value is NULL.
9292 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9295 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9297 MonoProperty* property;
9301 mono_class_setup_properties (klass);
9302 /* start from the first */
9303 if (klass->ext->property.count) {
9304 *iter = &klass->ext->properties [0];
9305 return (MonoProperty *)*iter;
9311 property = (MonoProperty *)*iter;
9313 if (property < &klass->ext->properties [klass->ext->property.count]) {
9315 return (MonoProperty *)*iter;
9321 * mono_class_get_events:
9322 * @klass: the MonoClass to act on
9324 * This routine is an iterator routine for retrieving the properties in a class.
9326 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9327 * iterate over all of the elements. When no more values are
9328 * available, the return value is NULL.
9330 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9333 mono_class_get_events (MonoClass* klass, gpointer *iter)
9339 mono_class_setup_events (klass);
9340 /* start from the first */
9341 if (klass->ext->event.count) {
9342 *iter = &klass->ext->events [0];
9343 return (MonoEvent *)*iter;
9349 event = (MonoEvent *)*iter;
9351 if (event < &klass->ext->events [klass->ext->event.count]) {
9353 return (MonoEvent *)*iter;
9359 * mono_class_get_interfaces
9360 * @klass: the MonoClass to act on
9362 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9364 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9365 * iterate over all of the elements. When no more values are
9366 * available, the return value is NULL.
9368 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9371 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9379 mono_class_init (klass);
9380 if (!klass->interfaces_inited) {
9381 mono_class_setup_interfaces (klass, &error);
9382 if (!mono_error_ok (&error)) {
9383 mono_error_cleanup (&error);
9387 /* start from the first */
9388 if (klass->interface_count) {
9389 *iter = &klass->interfaces [0];
9390 return klass->interfaces [0];
9396 iface = (MonoClass **)*iter;
9398 if (iface < &klass->interfaces [klass->interface_count]) {
9406 setup_nested_types (MonoClass *klass)
9409 GList *classes, *nested_classes, *l;
9412 if (klass->nested_classes_inited)
9415 if (!klass->type_token)
9416 klass->nested_classes_inited = TRUE;
9418 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9422 guint32 cols [MONO_NESTED_CLASS_SIZE];
9423 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9424 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9425 if (!mono_error_ok (&error)) {
9426 /*FIXME don't swallow the error message*/
9427 mono_error_cleanup (&error);
9429 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9433 classes = g_list_prepend (classes, nclass);
9435 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9438 mono_class_alloc_ext (klass);
9440 nested_classes = NULL;
9441 for (l = classes; l; l = l->next)
9442 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9443 g_list_free (classes);
9445 mono_image_lock (klass->image);
9447 mono_memory_barrier ();
9448 if (!klass->nested_classes_inited) {
9449 klass->ext->nested_classes = nested_classes;
9450 mono_memory_barrier ();
9451 klass->nested_classes_inited = TRUE;
9454 mono_image_unlock (klass->image);
9458 * mono_class_get_nested_types
9459 * @klass: the MonoClass to act on
9461 * This routine is an iterator routine for retrieving the nested types of a class.
9462 * This works only if @klass is non-generic, or a generic type definition.
9464 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9465 * iterate over all of the elements. When no more values are
9466 * available, the return value is NULL.
9468 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9471 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9477 if (!klass->nested_classes_inited)
9478 setup_nested_types (klass);
9481 /* start from the first */
9482 if (klass->ext && klass->ext->nested_classes) {
9483 *iter = klass->ext->nested_classes;
9484 return (MonoClass *)klass->ext->nested_classes->data;
9486 /* no nested types */
9490 item = (GList *)*iter;
9494 return (MonoClass *)item->data;
9501 * mono_class_is_delegate
9502 * @klass: the MonoClass to act on
9504 * Returns: TRUE if the MonoClass represents a System.Delegate.
9507 mono_class_is_delegate (MonoClass *klass)
9509 return klass->delegate;
9513 * mono_class_implements_interface
9514 * @klass: The MonoClass to act on
9515 * @interface: The interface to check if @klass implements.
9517 * Returns: TRUE if @klass implements @interface.
9520 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9522 return mono_class_is_assignable_from (iface, klass);
9526 * mono_field_get_name:
9527 * @field: the MonoClassField to act on
9529 * Returns: The name of the field.
9532 mono_field_get_name (MonoClassField *field)
9538 * mono_field_get_type:
9539 * @field: the MonoClassField to act on
9541 * Returns: MonoType of the field.
9544 mono_field_get_type (MonoClassField *field)
9547 MonoType *type = mono_field_get_type_checked (field, &error);
9548 if (!mono_error_ok (&error)) {
9549 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9550 mono_error_cleanup (&error);
9557 * mono_field_get_type_checked:
9558 * @field: the MonoClassField to act on
9559 * @error: used to return any erro found while retrieving @field type
9561 * Returns: MonoType of the field.
9564 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9566 mono_error_init (error);
9568 mono_field_resolve_type (field, error);
9573 * mono_field_get_parent:
9574 * @field: the MonoClassField to act on
9576 * Returns: MonoClass where the field was defined.
9579 mono_field_get_parent (MonoClassField *field)
9581 return field->parent;
9585 * mono_field_get_flags;
9586 * @field: the MonoClassField to act on
9588 * The metadata flags for a field are encoded using the
9589 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9591 * Returns: The flags for the field.
9594 mono_field_get_flags (MonoClassField *field)
9597 return mono_field_resolve_flags (field);
9598 return field->type->attrs;
9602 * mono_field_get_offset:
9603 * @field: the MonoClassField to act on
9605 * Returns: The field offset.
9608 mono_field_get_offset (MonoClassField *field)
9610 return field->offset;
9614 mono_field_get_rva (MonoClassField *field)
9618 MonoClass *klass = field->parent;
9619 MonoFieldDefaultValue *field_def_values;
9621 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9623 if (!klass->ext || !klass->ext->field_def_values) {
9624 mono_class_alloc_ext (klass);
9626 field_def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9628 mono_image_lock (klass->image);
9629 if (!klass->ext->field_def_values)
9630 klass->ext->field_def_values = field_def_values;
9631 mono_image_unlock (klass->image);
9634 field_index = mono_field_get_index (field);
9636 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9637 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9639 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9640 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9643 return klass->ext->field_def_values [field_index].data;
9647 * mono_field_get_data:
9648 * @field: the MonoClassField to act on
9650 * Returns: A pointer to the metadata constant value or to the field
9651 * data if it has an RVA flag.
9654 mono_field_get_data (MonoClassField *field)
9656 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9657 MonoTypeEnum def_type;
9659 return mono_class_get_field_default_value (field, &def_type);
9660 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9661 return mono_field_get_rva (field);
9668 * mono_property_get_name:
9669 * @prop: the MonoProperty to act on
9671 * Returns: The name of the property
9674 mono_property_get_name (MonoProperty *prop)
9680 * mono_property_get_set_method
9681 * @prop: the MonoProperty to act on.
9683 * Returns: The setter method of the property (A MonoMethod)
9686 mono_property_get_set_method (MonoProperty *prop)
9692 * mono_property_get_get_method
9693 * @prop: the MonoProperty to act on.
9695 * Returns: The setter method of the property (A MonoMethod)
9698 mono_property_get_get_method (MonoProperty *prop)
9704 * mono_property_get_parent:
9705 * @prop: the MonoProperty to act on.
9707 * Returns: The MonoClass where the property was defined.
9710 mono_property_get_parent (MonoProperty *prop)
9712 return prop->parent;
9716 * mono_property_get_flags:
9717 * @prop: the MonoProperty to act on.
9719 * The metadata flags for a property are encoded using the
9720 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9722 * Returns: The flags for the property.
9725 mono_property_get_flags (MonoProperty *prop)
9731 * mono_event_get_name:
9732 * @event: the MonoEvent to act on
9734 * Returns: The name of the event.
9737 mono_event_get_name (MonoEvent *event)
9743 * mono_event_get_add_method:
9744 * @event: The MonoEvent to act on.
9746 * Returns: The @add' method for the event (a MonoMethod).
9749 mono_event_get_add_method (MonoEvent *event)
9755 * mono_event_get_remove_method:
9756 * @event: The MonoEvent to act on.
9758 * Returns: The @remove method for the event (a MonoMethod).
9761 mono_event_get_remove_method (MonoEvent *event)
9763 return event->remove;
9767 * mono_event_get_raise_method:
9768 * @event: The MonoEvent to act on.
9770 * Returns: The @raise method for the event (a MonoMethod).
9773 mono_event_get_raise_method (MonoEvent *event)
9775 return event->raise;
9779 * mono_event_get_parent:
9780 * @event: the MonoEvent to act on.
9782 * Returns: The MonoClass where the event is defined.
9785 mono_event_get_parent (MonoEvent *event)
9787 return event->parent;
9791 * mono_event_get_flags
9792 * @event: the MonoEvent to act on.
9794 * The metadata flags for an event are encoded using the
9795 * EVENT_* constants. See the tabledefs.h file for details.
9797 * Returns: The flags for the event.
9800 mono_event_get_flags (MonoEvent *event)
9802 return event->attrs;
9806 * mono_class_get_method_from_name:
9807 * @klass: where to look for the method
9808 * @name: name of the method
9809 * @param_count: number of parameters. -1 for any number.
9811 * Obtains a MonoMethod with a given name and number of parameters.
9812 * It only works if there are no multiple signatures for any given method name.
9815 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9817 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9821 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9823 MonoMethod *res = NULL;
9826 /* Search directly in the metadata to avoid calling setup_methods () */
9827 for (i = 0; i < klass->method.count; ++i) {
9829 guint32 cols [MONO_METHOD_SIZE];
9831 MonoMethodSignature *sig;
9833 /* klass->method.first points into the methodptr table */
9834 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9836 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9837 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9839 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9842 if (param_count == -1) {
9846 sig = mono_method_signature_checked (method, &error);
9848 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9851 if (sig->param_count == param_count) {
9862 * mono_class_get_method_from_name_flags:
9863 * @klass: where to look for the method
9864 * @name_space: name of the method
9865 * @param_count: number of parameters. -1 for any number.
9866 * @flags: flags which must be set in the method
9868 * Obtains a MonoMethod with a given name and number of parameters.
9869 * It only works if there are no multiple signatures for any given method name.
9872 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9874 MonoMethod *res = NULL;
9877 mono_class_init (klass);
9879 if (klass->generic_class && !klass->methods) {
9880 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9883 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9884 if (!mono_error_ok (&error))
9885 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9890 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9891 mono_class_setup_methods (klass);
9893 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9894 See mono/tests/array_load_exception.il
9895 FIXME we should better report this error to the caller
9897 if (!klass->methods)
9899 for (i = 0; i < klass->method.count; ++i) {
9900 MonoMethod *method = klass->methods [i];
9902 if (method->name[0] == name [0] &&
9903 !strcmp (name, method->name) &&
9904 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9905 ((method->flags & flags) == flags)) {
9912 res = find_method_in_metadata (klass, name, param_count, flags);
9919 * mono_class_set_failure:
9920 * @klass: class in which the failure was detected
9921 * @ex_type: the kind of exception/error to be thrown (later)
9922 * @ex_data: exception data (specific to each type of exception/error)
9924 * Keep a detected failure informations in the class for later processing.
9925 * Note that only the first failure is kept.
9927 * LOCKING: Acquires the loader lock.
9930 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9932 if (mono_class_has_failure (klass))
9935 mono_loader_lock ();
9936 klass->exception_type = ex_type;
9938 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9939 mono_loader_unlock ();
9945 * mono_class_get_exception_data:
9947 * Return the exception_data property of KLASS.
9949 * LOCKING: Acquires the loader lock.
9952 mono_class_get_exception_data (MonoClass *klass)
9954 return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9958 * mono_classes_init:
9960 * Initialize the resources used by this module.
9963 mono_classes_init (void)
9965 mono_os_mutex_init (&classes_mutex);
9967 mono_counters_register ("Inflated methods size",
9968 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9969 mono_counters_register ("Inflated classes",
9970 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9971 mono_counters_register ("Inflated classes size",
9972 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9973 mono_counters_register ("MonoClass size",
9974 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9975 mono_counters_register ("MonoClassExt size",
9976 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
9980 * mono_classes_cleanup:
9982 * Free the resources used by this module.
9985 mono_classes_cleanup (void)
9987 if (global_interface_bitset)
9988 mono_bitset_free (global_interface_bitset);
9989 global_interface_bitset = NULL;
9990 mono_os_mutex_destroy (&classes_mutex);
9994 * mono_class_get_exception_for_failure:
9995 * @klass: class in which the failure was detected
9997 * Return a constructed MonoException than the caller can then throw
9998 * using mono_raise_exception - or NULL if no failure is present (or
9999 * doesn't result in an exception).
10002 mono_class_get_exception_for_failure (MonoClass *klass)
10004 gpointer exception_data = mono_class_get_exception_data (klass);
10006 switch (mono_class_get_failure(klass)) {
10007 case MONO_EXCEPTION_TYPE_LOAD: {
10010 char *str = mono_type_get_full_name (klass);
10011 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
10012 name = mono_string_new (mono_domain_get (), str);
10014 ex = mono_get_exception_type_load (name, astr);
10018 case MONO_EXCEPTION_MISSING_METHOD: {
10019 char *class_name = (char *)exception_data;
10020 char *assembly_name = class_name + strlen (class_name) + 1;
10022 return mono_get_exception_missing_method (class_name, assembly_name);
10024 case MONO_EXCEPTION_MISSING_FIELD: {
10025 char *class_name = (char *)exception_data;
10026 char *member_name = class_name + strlen (class_name) + 1;
10028 return mono_get_exception_missing_field (class_name, member_name);
10030 case MONO_EXCEPTION_FILE_NOT_FOUND: {
10031 char *msg_format = (char *)exception_data;
10032 char *assembly_name = msg_format + strlen (msg_format) + 1;
10033 char *msg = g_strdup_printf (msg_format, assembly_name);
10036 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
10042 case MONO_EXCEPTION_BAD_IMAGE: {
10043 return mono_get_exception_bad_image_format ((const char *)exception_data);
10045 case MONO_EXCEPTION_INVALID_PROGRAM: {
10046 return mono_exception_from_name_msg (mono_defaults.corlib, "System", "InvalidProgramException", "");
10049 /* TODO - handle other class related failures */
10050 return mono_get_exception_execution_engine ("Unknown class failure");
10056 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
10058 outer_klass = mono_class_get_generic_type_definition (outer_klass);
10059 inner_klass = mono_class_get_generic_type_definition (inner_klass);
10061 if (outer_klass == inner_klass)
10063 inner_klass = inner_klass->nested_in;
10064 } while (inner_klass);
10069 mono_class_get_generic_type_definition (MonoClass *klass)
10071 return klass->generic_class ? klass->generic_class->container_class : klass;
10075 * Check if @klass is a subtype of @parent ignoring generic instantiations.
10077 * Generic instantiations are ignored for all super types of @klass.
10079 * Visibility checks ignoring generic instantiations.
10082 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
10085 klass = mono_class_get_generic_type_definition (klass);
10086 parent = mono_class_get_generic_type_definition (parent);
10087 mono_class_setup_supertypes (klass);
10089 for (i = 0; i < klass->idepth; ++i) {
10090 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
10096 * Subtype can only access parent members with family protection if the site object
10097 * is subclass of Subtype. For example:
10098 * class A { protected int x; }
10100 * void valid_access () {
10104 * void invalid_access () {
10111 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
10113 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
10116 if (context_klass == NULL)
10118 /*if access_klass is not member_klass context_klass must be type compat*/
10119 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10125 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10128 if (accessing == accessed)
10130 if (!accessed || !accessing)
10133 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10134 * anywhere so untrusted friends are not safe to access platform's code internals */
10135 if (mono_security_core_clr_enabled ()) {
10136 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10140 mono_assembly_load_friends (accessed);
10141 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10142 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10143 /* Be conservative with checks */
10144 if (!friend_->name)
10146 if (strcmp (accessing->aname.name, friend_->name))
10148 if (friend_->public_key_token [0]) {
10149 if (!accessing->aname.public_key_token [0])
10151 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10160 * If klass is a generic type or if it is derived from a generic type, return the
10161 * MonoClass of the generic definition
10162 * Returns NULL if not found
10165 get_generic_definition_class (MonoClass *klass)
10168 if (klass->generic_class && klass->generic_class->container_class)
10169 return klass->generic_class->container_class;
10170 klass = klass->parent;
10176 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10179 for (i = 0; i < ginst->type_argc; ++i) {
10180 MonoType *type = ginst->type_argv[i];
10181 switch (type->type) {
10182 case MONO_TYPE_SZARRAY:
10183 if (!can_access_type (access_klass, type->data.klass))
10186 case MONO_TYPE_ARRAY:
10187 if (!can_access_type (access_klass, type->data.array->eklass))
10190 case MONO_TYPE_PTR:
10191 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10194 case MONO_TYPE_CLASS:
10195 case MONO_TYPE_VALUETYPE:
10196 case MONO_TYPE_GENERICINST:
10197 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10207 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10211 if (access_klass == member_klass)
10214 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10217 if (access_klass->element_class && !access_klass->enumtype)
10218 access_klass = access_klass->element_class;
10220 if (member_klass->element_class && !member_klass->enumtype)
10221 member_klass = member_klass->element_class;
10223 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10225 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10228 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
10231 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10234 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10237 /*Non nested type with nested visibility. We just fail it.*/
10238 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10241 switch (access_level) {
10242 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10243 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10245 case TYPE_ATTRIBUTE_PUBLIC:
10248 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10251 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10252 return is_nesting_type (member_klass, access_klass);
10254 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10255 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10257 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10258 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10260 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10261 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10262 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10264 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10265 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10266 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10271 /* FIXME: check visibility of type, too */
10273 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10275 MonoClass *member_generic_def;
10276 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10279 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
10280 access_klass->generic_container) &&
10281 (member_generic_def = get_generic_definition_class (member_klass))) {
10282 MonoClass *access_container;
10284 if (access_klass->generic_container)
10285 access_container = access_klass;
10287 access_container = access_klass->generic_class->container_class;
10289 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10293 /* Partition I 8.5.3.2 */
10294 /* the access level values are the same for fields and methods */
10295 switch (access_level) {
10296 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10297 /* same compilation unit */
10298 return access_klass->image == member_klass->image;
10299 case FIELD_ATTRIBUTE_PRIVATE:
10300 return access_klass == member_klass;
10301 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10302 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10303 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10306 case FIELD_ATTRIBUTE_ASSEMBLY:
10307 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10308 case FIELD_ATTRIBUTE_FAMILY:
10309 if (is_valid_family_access (access_klass, member_klass, context_klass))
10312 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10313 if (is_valid_family_access (access_klass, member_klass, context_klass))
10315 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10316 case FIELD_ATTRIBUTE_PUBLIC:
10323 * mono_method_can_access_field:
10324 * @method: Method that will attempt to access the field
10325 * @field: the field to access
10327 * Used to determine if a method is allowed to access the specified field.
10329 * Returns: TRUE if the given @method is allowed to access the @field while following
10330 * the accessibility rules of the CLI.
10333 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10335 /* FIXME: check all overlapping fields */
10336 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10338 MonoClass *nested = method->klass->nested_in;
10340 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10343 nested = nested->nested_in;
10350 * mono_method_can_access_method:
10351 * @method: Method that will attempt to access the other method
10352 * @called: the method that we want to probe for accessibility.
10354 * Used to determine if the @method is allowed to access the specified @called method.
10356 * Returns: TRUE if the given @method is allowed to invoke the @called while following
10357 * the accessibility rules of the CLI.
10360 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10362 method = mono_method_get_method_definition (method);
10363 called = mono_method_get_method_definition (called);
10364 return mono_method_can_access_method_full (method, called, NULL);
10368 * mono_method_can_access_method_full:
10369 * @method: The caller method
10370 * @called: The called method
10371 * @context_klass: The static type on stack of the owner @called object used
10373 * This function must be used with instance calls, as they have more strict family accessibility.
10374 * It can be used with static methods, but context_klass should be NULL.
10376 * Returns: TRUE if caller have proper visibility and acessibility to @called
10379 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10381 /* Wrappers are except from access checks */
10382 if (method->wrapper_type != MONO_WRAPPER_NONE || called->wrapper_type != MONO_WRAPPER_NONE)
10385 MonoClass *access_class = method->klass;
10386 MonoClass *member_class = called->klass;
10387 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10389 MonoClass *nested = access_class->nested_in;
10391 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10394 nested = nested->nested_in;
10401 can = can_access_type (access_class, member_class);
10403 MonoClass *nested = access_class->nested_in;
10405 can = can_access_type (nested, member_class);
10408 nested = nested->nested_in;
10415 if (called->is_inflated) {
10416 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10417 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10426 * mono_method_can_access_field_full:
10427 * @method: The caller method
10428 * @field: The accessed field
10429 * @context_klass: The static type on stack of the owner @field object used
10431 * This function must be used with instance fields, as they have more strict family accessibility.
10432 * It can be used with static fields, but context_klass should be NULL.
10434 * Returns: TRUE if caller have proper visibility and acessibility to @field
10437 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10439 MonoClass *access_class = method->klass;
10440 MonoClass *member_class = field->parent;
10441 /* FIXME: check all overlapping fields */
10442 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10444 MonoClass *nested = access_class->nested_in;
10446 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10449 nested = nested->nested_in;
10456 can = can_access_type (access_class, member_class);
10458 MonoClass *nested = access_class->nested_in;
10460 can = can_access_type (nested, member_class);
10463 nested = nested->nested_in;
10473 * mono_class_can_access_class:
10474 * @source_class: The source class
10475 * @target_class: The accessed class
10477 * This function returns is @target_class is visible to @source_class
10479 * Returns: TRUE if source have proper visibility and acessibility to target
10482 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10484 return can_access_type (source_class, target_class);
10488 * mono_type_is_valid_enum_basetype:
10489 * @type: The MonoType to check
10491 * Returns: TRUE if the type can be used as the basetype of an enum
10493 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10494 switch (type->type) {
10497 case MONO_TYPE_BOOLEAN:
10500 case MONO_TYPE_CHAR:
10514 * mono_class_is_valid_enum:
10515 * @klass: An enum class to be validated
10517 * This method verify the required properties an enum should have.
10519 * Returns: TRUE if the informed enum class is valid
10521 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10522 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10523 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10525 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10526 MonoClassField * field;
10527 gpointer iter = NULL;
10528 gboolean found_base_field = FALSE;
10530 g_assert (klass->enumtype);
10531 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10532 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10536 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10539 while ((field = mono_class_get_fields (klass, &iter))) {
10540 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10541 if (found_base_field)
10543 found_base_field = TRUE;
10544 if (!mono_type_is_valid_enum_basetype (field->type))
10549 if (!found_base_field)
10552 if (klass->method.count > 0)
10559 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10561 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10565 * mono_class_setup_interface_id:
10567 * Initializes MonoClass::interface_id if required.
10569 * LOCKING: Acquires the loader lock.
10572 mono_class_setup_interface_id (MonoClass *klass)
10574 mono_loader_lock ();
10575 if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10576 klass->interface_id = mono_get_unique_iid (klass);
10577 mono_loader_unlock ();
10581 * mono_class_alloc_ext:
10583 * Allocate klass->ext if not already done.
10586 mono_class_alloc_ext (MonoClass *klass)
10593 ext = (MonoClassExt *)mono_class_alloc0 (klass, sizeof (MonoClassExt));
10594 mono_image_lock (klass->image);
10595 mono_memory_barrier ();
10598 class_ext_size += sizeof (MonoClassExt);
10599 mono_image_unlock (klass->image);
10603 * mono_class_setup_interfaces:
10605 * Initialize klass->interfaces/interfaces_count.
10606 * LOCKING: Acquires the loader lock.
10607 * This function can fail the type.
10610 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10612 int i, interface_count;
10613 MonoClass **interfaces;
10615 mono_error_init (error);
10617 if (klass->interfaces_inited)
10620 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10621 MonoType *args [1];
10623 /* generic IList, ICollection, IEnumerable */
10624 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10625 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10627 args [0] = &klass->element_class->byval_arg;
10628 interfaces [0] = mono_class_bind_generic_parameters (
10629 mono_defaults.generic_ilist_class, 1, args, FALSE);
10630 if (interface_count > 1)
10631 interfaces [1] = mono_class_bind_generic_parameters (
10632 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10633 } else if (klass->generic_class) {
10634 MonoClass *gklass = klass->generic_class->container_class;
10636 mono_class_setup_interfaces (gklass, error);
10637 if (!mono_error_ok (error)) {
10638 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10642 interface_count = gklass->interface_count;
10643 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10644 for (i = 0; i < interface_count; i++) {
10645 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10646 if (!mono_error_ok (error)) {
10647 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10652 interface_count = 0;
10656 mono_image_lock (klass->image);
10658 if (!klass->interfaces_inited) {
10659 klass->interface_count = interface_count;
10660 klass->interfaces = interfaces;
10662 mono_memory_barrier ();
10664 klass->interfaces_inited = TRUE;
10667 mono_image_unlock (klass->image);
10671 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10673 MonoClass *klass = field->parent;
10674 MonoImage *image = klass->image;
10675 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10676 int field_idx = field - klass->fields;
10678 mono_error_init (error);
10681 MonoClassField *gfield = >d->fields [field_idx];
10682 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10683 if (!mono_error_ok (error)) {
10684 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10685 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10688 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10689 if (!mono_error_ok (error)) {
10690 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10691 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10695 guint32 cols [MONO_FIELD_SIZE];
10696 MonoGenericContainer *container = NULL;
10697 int idx = klass->field.first + field_idx;
10699 /*FIXME, in theory we do not lazy load SRE fields*/
10700 g_assert (!image_is_dynamic (image));
10702 if (klass->generic_container) {
10703 container = klass->generic_container;
10705 container = gtd->generic_container;
10706 g_assert (container);
10709 /* klass->field.first and idx points into the fieldptr table */
10710 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10712 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10713 mono_error_set_type_load_class (error, klass, "Could not verify field %s signature", field->name);;
10714 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
10718 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10720 mono_metadata_decode_value (sig, &sig);
10721 /* FIELD signature == 0x06 */
10722 g_assert (*sig == 0x06);
10724 field->type = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10725 if (!field->type) {
10726 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10727 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10733 mono_field_resolve_flags (MonoClassField *field)
10735 MonoClass *klass = field->parent;
10736 MonoImage *image = klass->image;
10737 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10738 int field_idx = field - klass->fields;
10742 MonoClassField *gfield = >d->fields [field_idx];
10743 return mono_field_get_flags (gfield);
10745 int idx = klass->field.first + field_idx;
10747 /*FIXME, in theory we do not lazy load SRE fields*/
10748 g_assert (!image_is_dynamic (image));
10750 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10755 * mono_class_setup_basic_field_info:
10756 * @class: The class to initialize
10758 * Initializes the klass->fields array of fields.
10759 * Aquires the loader lock.
10762 mono_class_setup_basic_field_info_locking (MonoClass *klass)
10764 mono_loader_lock ();
10765 mono_class_setup_basic_field_info (klass);
10766 mono_loader_unlock ();
10770 * mono_class_get_fields_lazy:
10771 * @klass: the MonoClass to act on
10773 * This routine is an iterator routine for retrieving the fields in a class.
10774 * Only minimal information about fields are loaded. Accessors must be used
10775 * for all MonoClassField returned.
10777 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10778 * iterate over all of the elements. When no more values are
10779 * available, the return value is NULL.
10781 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10784 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10786 MonoClassField* field;
10790 mono_class_setup_basic_field_info_locking (klass);
10791 if (!klass->fields)
10793 /* start from the first */
10794 if (klass->field.count) {
10795 *iter = &klass->fields [0];
10796 return (MonoClassField *)*iter;
10802 field = (MonoClassField *)*iter;
10804 if (field < &klass->fields [klass->field.count]) {
10806 return (MonoClassField *)*iter;
10812 mono_class_full_name (MonoClass *klass)
10814 return mono_type_full_name (&klass->byval_arg);
10817 /* Declare all shared lazy type lookup functions */
10818 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, System.Runtime.InteropServices, SafeHandle)