2 * class.c: Class management for the Mono runtime
5 * Miguel de Icaza (miguel@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9 * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
10 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
20 #include <mono/metadata/image.h>
21 #include <mono/metadata/image-internals.h>
22 #include <mono/metadata/assembly.h>
23 #include <mono/metadata/assembly-internals.h>
24 #include <mono/metadata/metadata.h>
25 #include <mono/metadata/metadata-internals.h>
26 #include <mono/metadata/profiler-private.h>
27 #include <mono/metadata/tabledefs.h>
28 #include <mono/metadata/tokentype.h>
29 #include <mono/metadata/class-internals.h>
30 #include <mono/metadata/object.h>
31 #include <mono/metadata/appdomain.h>
32 #include <mono/metadata/mono-endian.h>
33 #include <mono/metadata/debug-helpers.h>
34 #include <mono/metadata/reflection.h>
35 #include <mono/metadata/exception.h>
36 #include <mono/metadata/security-manager.h>
37 #include <mono/metadata/security-core-clr.h>
38 #include <mono/metadata/attrdefs.h>
39 #include <mono/metadata/gc-internals.h>
40 #include <mono/metadata/verify-internals.h>
41 #include <mono/metadata/mono-debug.h>
42 #include <mono/utils/mono-counters.h>
43 #include <mono/utils/mono-string.h>
44 #include <mono/utils/mono-error-internals.h>
45 #include <mono/utils/mono-logger-internals.h>
46 #include <mono/utils/mono-memory-model.h>
47 #include <mono/utils/atomic.h>
48 #include <mono/utils/bsearch.h>
49 #include <mono/utils/checked-build.h>
53 gboolean mono_print_vtable = FALSE;
54 gboolean mono_align_small_structs = FALSE;
57 guint32 inflated_classes_size, inflated_methods_size;
58 guint32 classes_size, class_ext_size, class_ext_count;
59 guint32 class_def_count, class_gtd_count, class_ginst_count, class_gparam_count, class_array_count, class_pointer_count;
61 /* Low level lock which protects data structures in this module */
62 static mono_mutex_t classes_mutex;
64 /* Function supplied by the runtime to find classes by name using information from the AOT file */
65 static MonoGetClassFromName get_class_from_name = NULL;
67 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error);
68 static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
69 static gboolean can_access_type (MonoClass *access_klass, MonoClass *member_klass);
70 static MonoMethod* find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags);
71 static int generic_array_methods (MonoClass *klass);
72 static void setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos);
74 static MonoMethod* mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter);
75 static char* mono_assembly_name_from_token (MonoImage *image, guint32 type_token);
76 static void mono_field_resolve_type (MonoClassField *field, MonoError *error);
77 static guint32 mono_field_resolve_flags (MonoClassField *field);
78 static void mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup);
79 static void mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gklass);
81 static gboolean mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error);
82 static gpointer mono_class_get_exception_data (const MonoClass *klass);
86 We use gclass recording to allow recursive system f types to be referenced by a parent.
88 Given the following type hierarchy:
90 class TextBox : TextBoxBase<TextBox> {}
91 class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
92 class TextInput<T> : Input<T> where T: TextInput<T> {}
95 The runtime tries to load TextBoxBase<>.
96 To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
97 To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
98 To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
100 At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded
101 at this point, iow, both are registered in the type map and both and a NULL parent. This means
102 that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
104 To fix that what we do is to record all generic instantes created while resolving the parent of
105 any generic type definition and, after resolved, correct the parent field if needed.
108 static int record_gclass_instantiation;
109 static GSList *gclass_recorded_list;
110 typedef gboolean (*gclass_record_func) (MonoClass*, void*);
112 /* This TLS variable points to a GSList of classes which have setup_fields () executing */
113 static MonoNativeTlsKey setup_fields_tls_id;
115 static MonoNativeTlsKey init_pending_tls_id;
120 mono_locks_os_acquire (&classes_mutex, ClassesLock);
124 classes_unlock (void)
126 mono_locks_os_release (&classes_mutex, ClassesLock);
130 * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
133 enable_gclass_recording (void)
135 ++record_gclass_instantiation;
139 * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
142 disable_gclass_recording (gclass_record_func func, void *user_data)
144 GSList **head = &gclass_recorded_list;
146 g_assert (record_gclass_instantiation > 0);
147 --record_gclass_instantiation;
150 GSList *node = *head;
151 if (func ((MonoClass*)node->data, user_data)) {
153 g_slist_free_1 (node);
159 /* We automatically discard all recorded gclasses when disabled. */
160 if (!record_gclass_instantiation && gclass_recorded_list) {
161 g_slist_free (gclass_recorded_list);
162 gclass_recorded_list = NULL;
167 * mono_class_from_typeref:
168 * @image: a MonoImage
169 * @type_token: a TypeRef token
171 * Creates the MonoClass* structure representing the type defined by
172 * the typeref token valid inside @image.
173 * Returns: The MonoClass* representing the typeref token, NULL ifcould
177 mono_class_from_typeref (MonoImage *image, guint32 type_token)
180 MonoClass *klass = mono_class_from_typeref_checked (image, type_token, &error);
181 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
186 * mono_class_from_typeref_checked:
187 * @image: a MonoImage
188 * @type_token: a TypeRef token
189 * @error: error return code, if any.
191 * Creates the MonoClass* structure representing the type defined by
192 * the typeref token valid inside @image.
194 * Returns: The MonoClass* representing the typeref token, NULL if it could
195 * not be loaded with the @error value filled with the information about the
199 mono_class_from_typeref_checked (MonoImage *image, guint32 type_token, MonoError *error)
201 guint32 cols [MONO_TYPEREF_SIZE];
202 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
204 const char *name, *nspace;
205 MonoClass *res = NULL;
208 mono_error_init (error);
210 if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, error))
213 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
215 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
216 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
218 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
219 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
220 case MONO_RESOLUTION_SCOPE_MODULE:
222 LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
223 This is not the observed behavior of existing implementations.
224 The defacto behavior is that it's just a typedef in disguise.
226 /* a typedef in disguise */
227 res = mono_class_from_name_checked (image, nspace, name, error);
230 case MONO_RESOLUTION_SCOPE_MODULEREF:
231 module = mono_image_load_module_checked (image, idx, error);
233 res = mono_class_from_name_checked (module, nspace, name, error);
236 case MONO_RESOLUTION_SCOPE_TYPEREF: {
237 MonoClass *enclosing;
240 if (idx == mono_metadata_token_index (type_token)) {
241 mono_error_set_bad_image (error, image, "Image with self-referencing typeref token %08x.", type_token);
245 enclosing = mono_class_from_typeref_checked (image, MONO_TOKEN_TYPE_REF | idx, error);
246 return_val_if_nok (error, NULL);
248 if (enclosing->nested_classes_inited && enclosing->ext) {
249 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
250 for (tmp = enclosing->ext->nested_classes; tmp; tmp = tmp->next) {
251 res = (MonoClass *)tmp->data;
252 if (strcmp (res->name, name) == 0)
256 /* Don't call mono_class_init as we might've been called by it recursively */
257 int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
259 guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
260 guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
261 const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
263 if (strcmp (nname, name) == 0)
264 return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, error);
266 i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
269 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name);
272 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
276 if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) {
277 mono_error_set_bad_image (error, image, "Image with invalid assemblyref token %08x.", idx);
281 if (!image->references || !image->references [idx - 1])
282 mono_assembly_load_reference (image, idx - 1);
283 g_assert (image->references [idx - 1]);
285 /* If the assembly did not load, register this as a type load exception */
286 if (image->references [idx - 1] == REFERENCE_MISSING){
287 MonoAssemblyName aname;
290 mono_assembly_get_assemblyref (image, idx - 1, &aname);
291 human_name = mono_stringify_assembly_name (&aname);
292 mono_error_set_assembly_load_simple (error, human_name, image->assembly ? image->assembly->ref_only : FALSE);
296 res = mono_class_from_name_checked (image->references [idx - 1]->image, nspace, name, error);
299 /* Generic case, should be avoided for when a better error is possible. */
300 if (!res && mono_error_ok (error)) {
301 char *name = mono_class_name_from_token (image, type_token);
302 char *assembly = mono_assembly_name_from_token (image, type_token);
303 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
310 mono_image_memdup (MonoImage *image, void *data, guint size)
312 void *res = mono_image_alloc (image, size);
313 memcpy (res, data, size);
317 /* Copy everything mono_metadata_free_array free. */
319 mono_dup_array_type (MonoImage *image, MonoArrayType *a)
322 a = (MonoArrayType *)mono_image_memdup (image, a, sizeof (MonoArrayType));
324 a->sizes = (int *)mono_image_memdup (image, a->sizes, a->numsizes * sizeof (int));
326 a->lobounds = (int *)mono_image_memdup (image, a->lobounds, a->numlobounds * sizeof (int));
328 a = (MonoArrayType *)g_memdup (a, sizeof (MonoArrayType));
330 a->sizes = (int *)g_memdup (a->sizes, a->numsizes * sizeof (int));
332 a->lobounds = (int *)g_memdup (a->lobounds, a->numlobounds * sizeof (int));
337 /* Copy everything mono_metadata_free_method_signature free. */
339 mono_metadata_signature_deep_dup (MonoImage *image, MonoMethodSignature *sig)
343 sig = mono_metadata_signature_dup_full (image, sig);
345 sig->ret = mono_metadata_type_dup (image, sig->ret);
346 for (i = 0; i < sig->param_count; ++i)
347 sig->params [i] = mono_metadata_type_dup (image, sig->params [i]);
353 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
355 MonoAssembly *ta = klass->image->assembly;
358 name = mono_stringify_assembly_name (&ta->aname);
359 g_string_append_printf (str, ", %s", name);
364 mono_type_name_check_byref (MonoType *type, GString *str)
367 g_string_append_c (str, '&');
371 * mono_identifier_escape_type_name_chars:
372 * @str: a destination string
373 * @identifier: an IDENTIFIER in internal form
377 * The displayed form of the identifier is appended to str.
379 * The displayed form of an identifier has the characters ,+&*[]\
380 * that have special meaning in type names escaped with a preceeding
381 * backslash (\) character.
384 mono_identifier_escape_type_name_chars (GString* str, const char* identifier)
390 // reserve space for common case: there will be no escaped characters.
391 g_string_set_size(str, n + strlen(identifier));
392 g_string_set_size(str, n);
394 for (const char* s = identifier; *s != 0 ; s++) {
403 g_string_append_c (str, '\\');
404 g_string_append_c (str, *s);
407 g_string_append_c (str, *s);
415 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
416 MonoTypeNameFormat format)
420 switch (type->type) {
421 case MONO_TYPE_ARRAY: {
422 int i, rank = type->data.array->rank;
423 MonoTypeNameFormat nested_format;
425 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
426 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
428 mono_type_get_name_recurse (
429 &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
430 g_string_append_c (str, '[');
432 g_string_append_c (str, '*');
433 for (i = 1; i < rank; i++)
434 g_string_append_c (str, ',');
435 g_string_append_c (str, ']');
437 mono_type_name_check_byref (type, str);
439 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
440 _mono_type_get_assembly_name (type->data.array->eklass, str);
443 case MONO_TYPE_SZARRAY: {
444 MonoTypeNameFormat nested_format;
446 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
447 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
449 mono_type_get_name_recurse (
450 &type->data.klass->byval_arg, str, FALSE, nested_format);
451 g_string_append (str, "[]");
453 mono_type_name_check_byref (type, str);
455 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
456 _mono_type_get_assembly_name (type->data.klass, str);
459 case MONO_TYPE_PTR: {
460 MonoTypeNameFormat nested_format;
462 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
463 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
465 mono_type_get_name_recurse (
466 type->data.type, str, FALSE, nested_format);
467 g_string_append_c (str, '*');
469 mono_type_name_check_byref (type, str);
471 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
472 _mono_type_get_assembly_name (mono_class_from_mono_type (type->data.type), str);
477 if (!mono_generic_param_info (type->data.generic_param))
478 g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num);
480 g_string_append (str, mono_generic_param_info (type->data.generic_param)->name);
482 mono_type_name_check_byref (type, str);
486 klass = mono_class_from_mono_type (type);
487 if (klass->nested_in) {
488 mono_type_get_name_recurse (
489 &klass->nested_in->byval_arg, str, TRUE, format);
490 if (format == MONO_TYPE_NAME_FORMAT_IL)
491 g_string_append_c (str, '.');
493 g_string_append_c (str, '+');
494 } else if (*klass->name_space) {
495 if (format == MONO_TYPE_NAME_FORMAT_IL)
496 g_string_append (str, klass->name_space);
498 mono_identifier_escape_type_name_chars (str, klass->name_space);
499 g_string_append_c (str, '.');
501 if (format == MONO_TYPE_NAME_FORMAT_IL) {
502 char *s = strchr (klass->name, '`');
503 int len = s ? s - klass->name : strlen (klass->name);
504 g_string_append_len (str, klass->name, len);
506 mono_identifier_escape_type_name_chars (str, klass->name);
510 if (mono_class_is_ginst (klass)) {
511 MonoGenericClass *gclass = mono_class_get_generic_class (klass);
512 MonoGenericInst *inst = gclass->context.class_inst;
513 MonoTypeNameFormat nested_format;
516 nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
517 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
519 if (format == MONO_TYPE_NAME_FORMAT_IL)
520 g_string_append_c (str, '<');
522 g_string_append_c (str, '[');
523 for (i = 0; i < inst->type_argc; i++) {
524 MonoType *t = inst->type_argv [i];
527 g_string_append_c (str, ',');
528 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
529 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
530 g_string_append_c (str, '[');
531 mono_type_get_name_recurse (inst->type_argv [i], str, FALSE, nested_format);
532 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
533 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
534 g_string_append_c (str, ']');
536 if (format == MONO_TYPE_NAME_FORMAT_IL)
537 g_string_append_c (str, '>');
539 g_string_append_c (str, ']');
540 } else if (mono_class_is_gtd (klass) &&
541 (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
542 (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
545 if (format == MONO_TYPE_NAME_FORMAT_IL)
546 g_string_append_c (str, '<');
548 g_string_append_c (str, '[');
549 for (i = 0; i < mono_class_get_generic_container (klass)->type_argc; i++) {
551 g_string_append_c (str, ',');
552 g_string_append (str, mono_generic_container_get_param_info (mono_class_get_generic_container (klass), i)->name);
554 if (format == MONO_TYPE_NAME_FORMAT_IL)
555 g_string_append_c (str, '>');
557 g_string_append_c (str, ']');
560 mono_type_name_check_byref (type, str);
562 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
563 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
564 _mono_type_get_assembly_name (klass, str);
570 * mono_type_get_name_full:
572 * @format: the format for the return string.
575 * Returns: The string representation in a number of formats:
577 * if format is MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
578 * returned in the formatrequired by System.Reflection, this is the
579 * inverse of mono_reflection_parse_type ().
581 * if format is MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
582 * be used by the IL assembler.
584 * if format is MONO_TYPE_NAME_FORMAT_FULL_NAME
586 * if format is MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
589 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
593 result = g_string_new ("");
595 mono_type_get_name_recurse (type, result, FALSE, format);
597 return g_string_free (result, FALSE);
601 * mono_type_get_full_name:
604 * Returns: The string representation for type as required by System.Reflection.
605 * The inverse of mono_reflection_parse_type ().
608 mono_type_get_full_name (MonoClass *klass)
610 return mono_type_get_name_full (mono_class_get_type (klass), MONO_TYPE_NAME_FORMAT_REFLECTION);
614 * mono_type_get_name:
617 * Returns: The string representation for type as it would be represented in IL code.
620 mono_type_get_name (MonoType *type)
622 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
626 * mono_type_get_underlying_type:
629 * Returns: The MonoType for the underlying integer type if @type
630 * is an enum and byref is false, otherwise the type itself.
633 mono_type_get_underlying_type (MonoType *type)
635 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype && !type->byref)
636 return mono_class_enum_basetype (type->data.klass);
637 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype && !type->byref)
638 return mono_class_enum_basetype (type->data.generic_class->container_class);
643 * mono_class_is_open_constructed_type:
646 * Returns: TRUE if type represents a generics open constructed type.
647 * IOW, not all type parameters required for the instantiation have
648 * been provided or it's a generic type definition.
650 * An open constructed type means it's a non realizable type. Not to
651 * be mixed up with an abstract type - we can't cast or dispatch to
652 * an open type, for example.
655 mono_class_is_open_constructed_type (MonoType *t)
661 case MONO_TYPE_SZARRAY:
662 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
663 case MONO_TYPE_ARRAY:
664 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
666 return mono_class_is_open_constructed_type (t->data.type);
667 case MONO_TYPE_GENERICINST:
668 return t->data.generic_class->context.class_inst->is_open;
669 case MONO_TYPE_CLASS:
670 case MONO_TYPE_VALUETYPE:
671 return mono_class_is_gtd (t->data.klass);
678 This is a simple function to catch the most common bad instances of generic types.
679 Specially those that might lead to further failures in the runtime.
682 is_valid_generic_argument (MonoType *type)
684 switch (type->type) {
686 //case MONO_TYPE_TYPEDBYREF:
694 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
696 mono_error_init (error);
698 switch (type->type) {
699 case MONO_TYPE_MVAR: {
701 int num = mono_type_get_generic_param_num (type);
702 MonoGenericInst *inst = context->method_inst;
705 if (num >= inst->type_argc) {
706 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
707 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
708 num, info ? info->name : "", inst->type_argc);
712 if (!is_valid_generic_argument (inst->type_argv [num])) {
713 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
714 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
715 num, info ? info->name : "", inst->type_argv [num]->type);
719 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
720 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
721 * ->byref and ->attrs from @type are propagated to the returned type.
723 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
724 nt->byref = type->byref;
725 nt->attrs = type->attrs;
728 case MONO_TYPE_VAR: {
730 int num = mono_type_get_generic_param_num (type);
731 MonoGenericInst *inst = context->class_inst;
734 if (num >= inst->type_argc) {
735 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
736 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
737 num, info ? info->name : "", inst->type_argc);
740 if (!is_valid_generic_argument (inst->type_argv [num])) {
741 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
742 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
743 num, info ? info->name : "", inst->type_argv [num]->type);
746 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
747 nt->byref = type->byref;
748 nt->attrs = type->attrs;
751 case MONO_TYPE_SZARRAY: {
752 MonoClass *eclass = type->data.klass;
753 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
754 if (!inflated || !mono_error_ok (error))
756 nt = mono_metadata_type_dup (image, type);
757 nt->data.klass = mono_class_from_mono_type (inflated);
758 mono_metadata_free_type (inflated);
761 case MONO_TYPE_ARRAY: {
762 MonoClass *eclass = type->data.array->eklass;
763 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
764 if (!inflated || !mono_error_ok (error))
766 nt = mono_metadata_type_dup (image, type);
767 nt->data.array->eklass = mono_class_from_mono_type (inflated);
768 mono_metadata_free_type (inflated);
771 case MONO_TYPE_GENERICINST: {
772 MonoGenericClass *gclass = type->data.generic_class;
773 MonoGenericInst *inst;
775 if (!gclass->context.class_inst->is_open)
778 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
779 return_val_if_nok (error, NULL);
781 if (inst != gclass->context.class_inst)
782 gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
784 if (gclass == type->data.generic_class)
787 nt = mono_metadata_type_dup (image, type);
788 nt->data.generic_class = gclass;
791 case MONO_TYPE_CLASS:
792 case MONO_TYPE_VALUETYPE: {
793 MonoClass *klass = type->data.klass;
794 MonoGenericContainer *container = mono_class_try_get_generic_container (klass);
795 MonoGenericInst *inst;
796 MonoGenericClass *gclass = NULL;
802 /* We can't use context->class_inst directly, since it can have more elements */
803 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
804 return_val_if_nok (error, NULL);
806 if (inst == container->context.class_inst)
809 gclass = mono_metadata_lookup_generic_class (klass, inst, image_is_dynamic (klass->image));
811 nt = mono_metadata_type_dup (image, type);
812 nt->type = MONO_TYPE_GENERICINST;
813 nt->data.generic_class = gclass;
823 mono_generic_class_get_context (MonoGenericClass *gclass)
825 return &gclass->context;
829 mono_class_get_context (MonoClass *klass)
831 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
832 return gklass ? mono_generic_class_get_context (gklass) : NULL;
836 * mono_class_inflate_generic_type_with_mempool:
837 * @mempool: a mempool
839 * @context: a generics context
840 * @error: error context
842 * The same as mono_class_inflate_generic_type, but allocates the MonoType
843 * from mempool if it is non-NULL. If it is NULL, the MonoType is
844 * allocated on the heap and is owned by the caller.
845 * The returned type can potentially be the same as TYPE, so it should not be
846 * modified by the caller, and it should be freed using mono_metadata_free_type ().
849 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
851 MonoType *inflated = NULL;
852 mono_error_init (error);
855 inflated = inflate_generic_type (image, type, context, error);
856 return_val_if_nok (error, NULL);
859 MonoType *shared = mono_metadata_get_shared_type (type);
864 return mono_metadata_type_dup (image, type);
868 mono_stats.inflated_type_count++;
873 * mono_class_inflate_generic_type:
875 * @context: a generics context
877 * If @type is a generic type and @context is not NULL, instantiate it using the
878 * generics context @context.
880 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
881 * on the heap and is owned by the caller. Returns NULL on error.
883 * @deprecated Please use mono_class_inflate_generic_type_checked instead
886 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
890 result = mono_class_inflate_generic_type_checked (type, context, &error);
891 mono_error_cleanup (&error);
896 * mono_class_inflate_generic_type:
898 * @context: a generics context
899 * @error: error context to use
901 * If @type is a generic type and @context is not NULL, instantiate it using the
902 * generics context @context.
904 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
905 * on the heap and is owned by the caller.
908 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
910 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
914 * mono_class_inflate_generic_type_no_copy:
916 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
920 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
922 MonoType *inflated = NULL;
924 mono_error_init (error);
926 inflated = inflate_generic_type (image, type, context, error);
927 return_val_if_nok (error, NULL);
933 mono_stats.inflated_type_count++;
938 * mono_class_inflate_generic_class:
940 * Inflate the class @gklass with @context. Set @error on failure.
943 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
948 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
949 return_val_if_nok (error, NULL);
951 res = mono_class_from_mono_type (inflated);
952 mono_metadata_free_type (inflated);
957 static MonoGenericContext
958 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
960 MonoGenericInst *class_inst = NULL;
961 MonoGenericInst *method_inst = NULL;
962 MonoGenericContext res = { NULL, NULL };
964 mono_error_init (error);
966 if (context->class_inst) {
967 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
968 if (!mono_error_ok (error))
972 if (context->method_inst) {
973 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
974 if (!mono_error_ok (error))
978 res.class_inst = class_inst;
979 res.method_inst = method_inst;
985 * mono_class_inflate_generic_method:
986 * @method: a generic method
987 * @context: a generics context
989 * Instantiate the generic method @method using the generics context @context.
991 * Returns: The new instantiated method
994 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
996 return mono_class_inflate_generic_method_full (method, NULL, context);
1000 mono_class_inflate_generic_method_checked (MonoMethod *method, MonoGenericContext *context, MonoError *error)
1002 return mono_class_inflate_generic_method_full_checked (method, NULL, context, error);
1006 * mono_class_inflate_generic_method_full:
1008 * Instantiate method @method with the generic context @context.
1009 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
1010 * Use mono_method_signature () and mono_method_get_header () to get the correct values.
1013 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
1016 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
1017 if (!mono_error_ok (&error))
1018 /*FIXME do proper error handling - on this case, kill this function. */
1019 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
1025 * mono_class_inflate_generic_method_full_checked:
1026 * Same as mono_class_inflate_generic_method_full but return failure using @error.
1029 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
1032 MonoMethodInflated *iresult, *cached;
1033 MonoMethodSignature *sig;
1034 MonoGenericContext tmp_context;
1036 mono_error_init (error);
1038 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1039 while (method->is_inflated) {
1040 MonoGenericContext *method_context = mono_method_get_context (method);
1041 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1043 tmp_context = inflate_generic_context (method_context, context, error);
1044 return_val_if_nok (error, NULL);
1046 context = &tmp_context;
1048 if (mono_metadata_generic_context_equal (method_context, context))
1051 method = imethod->declaring;
1055 * A method only needs to be inflated if the context has argument for which it is
1058 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1059 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1062 if (!((method->is_generic && context->method_inst) ||
1063 (mono_class_is_gtd (method->klass) && context->class_inst)))
1066 iresult = g_new0 (MonoMethodInflated, 1);
1067 iresult->context = *context;
1068 iresult->declaring = method;
1070 if (!context->method_inst && method->is_generic)
1071 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1073 if (!context->class_inst) {
1074 g_assert (!mono_class_is_ginst (iresult->declaring->klass));
1075 if (mono_class_is_gtd (iresult->declaring->klass))
1076 iresult->context.class_inst = mono_class_get_generic_container (iresult->declaring->klass)->context.class_inst;
1078 /* This can happen with some callers like mono_object_get_virtual_method () */
1079 if (!mono_class_is_gtd (iresult->declaring->klass) && !mono_class_is_ginst (iresult->declaring->klass))
1080 iresult->context.class_inst = NULL;
1082 MonoImageSet *set = mono_metadata_get_image_set_for_method (iresult);
1085 mono_image_set_lock (set);
1086 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1087 mono_image_set_unlock (set);
1091 return (MonoMethod*)cached;
1094 mono_stats.inflated_method_count++;
1096 inflated_methods_size += sizeof (MonoMethodInflated);
1098 sig = mono_method_signature (method);
1100 char *name = mono_type_get_full_name (method->klass);
1101 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1107 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1109 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1112 result = (MonoMethod *) iresult;
1113 result->is_inflated = TRUE;
1114 result->is_generic = FALSE;
1115 result->sre_method = FALSE;
1116 result->signature = NULL;
1118 if (method->wrapper_type) {
1119 MonoMethodWrapper *mw = (MonoMethodWrapper*)method;
1120 MonoMethodWrapper *resw = (MonoMethodWrapper*)result;
1121 int len = GPOINTER_TO_INT (((void**)mw->method_data) [0]);
1123 resw->method_data = (void **)g_malloc (sizeof (gpointer) * (len + 1));
1124 memcpy (resw->method_data, mw->method_data, sizeof (gpointer) * (len + 1));
1127 if (iresult->context.method_inst) {
1128 /* Set the generic_container of the result to the generic_container of method */
1129 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1131 if (generic_container && iresult->context.method_inst == generic_container->context.method_inst) {
1132 result->is_generic = 1;
1133 mono_method_set_generic_container (result, generic_container);
1138 MonoGenericClass *gklass_hint = mono_class_try_get_generic_class (klass_hint);
1139 if (gklass_hint && (gklass_hint->container_class != method->klass || gklass_hint->context.class_inst != context->class_inst))
1143 if (mono_class_is_gtd (method->klass))
1144 result->klass = klass_hint;
1146 if (!result->klass) {
1147 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1148 if (!mono_error_ok (error))
1151 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1153 mono_metadata_free_type (inflated);
1157 * FIXME: This should hold, but it doesn't:
1159 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1160 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1161 * g_assert (result->is_generic);
1164 * Fixing this here causes other things to break, hence a very
1165 * ugly hack in mini-trampolines.c - see
1166 * is_generic_method_definition().
1170 mono_image_set_lock (set);
1171 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1173 g_hash_table_insert (set->gmethod_cache, iresult, iresult);
1174 iresult->owner = set;
1177 mono_image_set_unlock (set);
1179 return (MonoMethod*)cached;
1187 * mono_get_inflated_method:
1189 * Obsolete. We keep it around since it's mentioned in the public API.
1192 mono_get_inflated_method (MonoMethod *method)
1198 * mono_method_get_context_general:
1200 * @uninflated: handle uninflated methods?
1202 * Returns the generic context of a method or NULL if it doesn't have
1203 * one. For an inflated method that's the context stored in the
1204 * method. Otherwise it's in the method's generic container or in the
1205 * generic container of the method's class.
1208 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1210 if (method->is_inflated) {
1211 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1212 return &imethod->context;
1216 if (method->is_generic)
1217 return &(mono_method_get_generic_container (method)->context);
1218 if (mono_class_is_gtd (method->klass))
1219 return &mono_class_get_generic_container (method->klass)->context;
1224 * mono_method_get_context:
1227 * Returns the generic context for method if it's inflated, otherwise
1231 mono_method_get_context (MonoMethod *method)
1233 return mono_method_get_context_general (method, FALSE);
1237 * mono_method_get_generic_container:
1239 * Returns the generic container of METHOD, which should be a generic method definition.
1240 * Returns NULL if METHOD is not a generic method definition.
1241 * LOCKING: Acquires the loader lock.
1243 MonoGenericContainer*
1244 mono_method_get_generic_container (MonoMethod *method)
1246 MonoGenericContainer *container;
1248 if (!method->is_generic)
1251 container = (MonoGenericContainer *)mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1252 g_assert (container);
1258 * mono_method_set_generic_container:
1260 * Sets the generic container of METHOD to CONTAINER.
1261 * LOCKING: Acquires the image lock.
1264 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1266 g_assert (method->is_generic);
1268 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1272 * mono_class_find_enum_basetype:
1273 * @class: The enum class
1275 * Determine the basetype of an enum by iterating through its fields. We do this
1276 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1279 mono_class_find_enum_basetype (MonoClass *klass, MonoError *error)
1281 MonoGenericContainer *container = NULL;
1282 MonoImage *m = klass->image;
1283 const int top = klass->field.count;
1286 g_assert (klass->enumtype);
1288 mono_error_init (error);
1290 container = mono_class_try_get_generic_container (klass);
1291 if (mono_class_is_ginst (klass)) {
1292 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
1294 container = mono_class_get_generic_container (gklass);
1295 g_assert (container);
1299 * Fetch all the field information.
1301 for (i = 0; i < top; i++){
1303 guint32 cols [MONO_FIELD_SIZE];
1304 int idx = klass->field.first + i;
1307 /* klass->field.first and idx points into the fieldptr table */
1308 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1310 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1313 if (!mono_verifier_verify_field_signature (klass->image, cols [MONO_FIELD_SIGNATURE], NULL)) {
1314 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x", cols [MONO_FIELD_SIGNATURE]);
1318 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1319 mono_metadata_decode_value (sig, &sig);
1320 /* FIELD signature == 0x06 */
1322 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig);
1326 ftype = mono_metadata_parse_type_checked (m, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
1330 if (mono_class_is_ginst (klass)) {
1331 //FIXME do we leak here?
1332 ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (klass), error);
1333 if (!mono_error_ok (error))
1335 ftype->attrs = cols [MONO_FIELD_FLAGS];
1340 mono_error_set_type_load_class (error, klass, "Could not find base type");
1347 * Checks for MonoClass::has_failure without resolving all MonoType's into MonoClass'es
1350 mono_type_has_exceptions (MonoType *type)
1352 switch (type->type) {
1353 case MONO_TYPE_CLASS:
1354 case MONO_TYPE_VALUETYPE:
1355 case MONO_TYPE_SZARRAY:
1356 return mono_class_has_failure (type->data.klass);
1357 case MONO_TYPE_ARRAY:
1358 return mono_class_has_failure (type->data.array->eklass);
1359 case MONO_TYPE_GENERICINST:
1360 return mono_class_has_failure (mono_generic_class_get_class (type->data.generic_class));
1367 mono_error_set_for_class_failure (MonoError *oerror, const MonoClass *klass)
1369 g_assert (mono_class_has_failure (klass));
1370 MonoErrorBoxed *box = (MonoErrorBoxed*)mono_class_get_exception_data (klass);
1371 mono_error_set_from_boxed (oerror, box);
1378 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1382 mono_class_alloc (MonoClass *klass, int size)
1384 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
1386 return mono_image_set_alloc (gklass->owner, size);
1388 return mono_image_alloc (klass->image, size);
1392 mono_class_alloc0 (MonoClass *klass, int size)
1396 res = mono_class_alloc (klass, size);
1397 memset (res, 0, size);
1401 #define mono_class_new0(klass,struct_type, n_structs) \
1402 ((struct_type *) mono_class_alloc0 ((klass), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1405 * mono_class_setup_basic_field_info:
1406 * @class: The class to initialize
1408 * Initializes the following fields in MonoClass:
1409 * * klass->fields (only field->parent and field->name)
1410 * * klass->field.count
1411 * * klass->field.first
1412 * LOCKING: Acquires the loader lock
1415 mono_class_setup_basic_field_info (MonoClass *klass)
1417 MonoGenericClass *gklass;
1418 MonoClassField *field;
1419 MonoClassField *fields;
1427 gklass = mono_class_try_get_generic_class (klass);
1428 gtd = gklass ? mono_class_get_generic_type_definition (klass) : NULL;
1429 image = klass->image;
1432 if (gklass && image_is_dynamic (gklass->container_class->image) && !gklass->container_class->wastypebuilder) {
1434 * This happens when a generic instance of an unfinished generic typebuilder
1435 * is used as an element type for creating an array type. We can't initialize
1436 * the fields of this class using the fields of gklass, since gklass is not
1437 * finished yet, fields could be added to it later.
1443 mono_class_setup_basic_field_info (gtd);
1445 mono_loader_lock ();
1446 klass->field.first = gtd->field.first;
1447 klass->field.count = gtd->field.count;
1448 mono_loader_unlock ();
1451 top = klass->field.count;
1453 fields = (MonoClassField *)mono_class_alloc0 (klass, sizeof (MonoClassField) * top);
1456 * Fetch all the field information.
1458 for (i = 0; i < top; i++){
1459 field = &fields [i];
1460 field->parent = klass;
1463 field->name = mono_field_get_name (>d->fields [i]);
1465 int idx = klass->field.first + i;
1466 /* klass->field.first and idx points into the fieldptr table */
1467 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1468 /* The name is needed for fieldrefs */
1469 field->name = mono_metadata_string_heap (image, name_idx);
1473 mono_memory_barrier ();
1475 mono_loader_lock ();
1477 klass->fields = fields;
1478 mono_loader_unlock ();
1482 * mono_class_set_failure_causedby_class:
1483 * @klass: the class that is failing
1484 * @caused_by: the class that caused the failure
1485 * @msg: Why @klass is failing.
1487 * If @caused_by has a failure, sets a TypeLoadException failure on
1488 * @klass with message "@msg, due to: {@caused_by message}".
1490 * Returns: TRUE if a failiure was set, or FALSE if @caused_by doesn't have a failure.
1493 mono_class_set_type_load_failure_causedby_class (MonoClass *klass, const MonoClass *caused_by, const gchar* msg)
1495 if (mono_class_has_failure (caused_by)) {
1496 MonoError cause_error;
1497 mono_error_init (&cause_error);
1498 mono_error_set_for_class_failure (&cause_error, caused_by);
1499 mono_class_set_type_load_failure (klass, "%s, due to: %s", msg, mono_error_get_message (&cause_error));
1500 mono_error_cleanup (&cause_error);
1509 * mono_class_setup_fields:
1510 * @klass: The class to initialize
1512 * Initializes klass->fields, computes class layout and sizes.
1513 * typebuilder_setup_fields () is the corresponding function for dynamic classes.
1514 * Sets the following fields in @klass:
1515 * - all the fields initialized by mono_class_init_sizes ()
1516 * - element_class/cast_class (for enums)
1517 * - field->type/offset for all fields
1520 * LOCKING: Acquires the loader lock.
1523 mono_class_setup_fields (MonoClass *klass)
1526 MonoImage *m = klass->image;
1528 guint32 layout = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK;
1530 guint32 real_size = 0;
1531 guint32 packing_size = 0;
1533 gboolean explicit_size;
1534 MonoClassField *field;
1535 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
1536 MonoClass *gtd = gklass ? mono_class_get_generic_type_definition (klass) : NULL;
1538 if (klass->fields_inited)
1541 if (gklass && image_is_dynamic (gklass->container_class->image) && !gklass->container_class->wastypebuilder) {
1543 * This happens when a generic instance of an unfinished generic typebuilder
1544 * is used as an element type for creating an array type. We can't initialize
1545 * the fields of this class using the fields of gklass, since gklass is not
1546 * finished yet, fields could be added to it later.
1551 mono_class_setup_basic_field_info (klass);
1552 top = klass->field.count;
1555 mono_class_setup_fields (gtd);
1556 if (mono_class_set_type_load_failure_causedby_class (klass, gtd, "Generic type definition failed"))
1561 if (klass->parent) {
1562 /* For generic instances, klass->parent might not have been initialized */
1563 mono_class_init (klass->parent);
1564 mono_class_setup_fields (klass->parent);
1565 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Could not set up parent class"))
1567 instance_size = klass->parent->instance_size;
1569 instance_size = sizeof (MonoObject);
1572 /* Get the real size */
1573 explicit_size = mono_metadata_packing_from_typedef (klass->image, klass->type_token, &packing_size, &real_size);
1575 instance_size += real_size;
1578 * This function can recursively call itself.
1579 * Prevent infinite recursion by using a list in TLS.
1581 GSList *init_list = (GSList *)mono_native_tls_get_value (setup_fields_tls_id);
1582 if (g_slist_find (init_list, klass))
1584 init_list = g_slist_prepend (init_list, klass);
1585 mono_native_tls_set_value (setup_fields_tls_id, init_list);
1588 * Fetch all the field information.
1590 for (i = 0; i < top; i++) {
1591 int idx = klass->field.first + i;
1592 field = &klass->fields [i];
1595 mono_field_resolve_type (field, &error);
1596 if (!mono_error_ok (&error)) {
1597 /*mono_field_resolve_type already failed class*/
1598 mono_error_cleanup (&error);
1602 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(klass), field->name);
1603 g_assert (field->type);
1606 if (mono_field_is_deleted (field))
1608 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1610 mono_metadata_field_info (m, idx, &uoffset, NULL, NULL);
1611 int offset = uoffset;
1613 if (offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1614 mono_class_set_type_load_failure (klass, "Missing field layout info for %s", field->name);
1617 if (offset < -1) { /*-1 is used to encode special static fields */
1618 mono_class_set_type_load_failure (klass, "Field '%s' has a negative offset %d", field->name, offset);
1621 if (mono_class_is_gtd (klass)) {
1622 mono_class_set_type_load_failure (klass, "Generic class cannot have explicit layout.");
1626 if (mono_type_has_exceptions (field->type)) {
1627 char *class_name = mono_type_get_full_name (klass);
1628 char *type_name = mono_type_full_name (field->type);
1630 mono_class_set_type_load_failure (klass, "");
1631 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1632 g_free (class_name);
1636 /* The def_value of fields is compute lazily during vtable creation */
1639 if (!mono_class_has_failure (klass))
1640 mono_class_layout_fields (klass, instance_size, packing_size, FALSE);
1642 init_list = g_slist_remove (init_list, klass);
1643 mono_native_tls_set_value (setup_fields_tls_id, init_list);
1647 init_sizes_with_info (MonoClass *klass, MonoCachedClassInfo *cached_info)
1650 klass->instance_size = cached_info->instance_size;
1651 klass->sizes.class_size = cached_info->class_size;
1652 klass->packing_size = cached_info->packing_size;
1653 klass->min_align = cached_info->min_align;
1654 klass->blittable = cached_info->blittable;
1655 klass->has_references = cached_info->has_references;
1656 klass->has_static_refs = cached_info->has_static_refs;
1657 klass->no_special_static_fields = cached_info->no_special_static_fields;
1660 if (!klass->size_inited)
1661 mono_class_setup_fields (klass);
1666 * mono_class_init_sizes:
1668 * Initializes the size related fields of @klass without loading all field data if possible.
1669 * Sets the following fields in @klass:
1671 * - sizes.class_size
1678 * Can fail the class.
1680 * LOCKING: Acquires the loader lock.
1683 mono_class_init_sizes (MonoClass *klass)
1685 MonoCachedClassInfo cached_info;
1686 gboolean has_cached_info;
1688 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
1690 init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
1694 * mono_type_get_basic_type_from_generic:
1697 * Returns a closed type corresponding to the possibly open type
1701 mono_type_get_basic_type_from_generic (MonoType *type)
1703 /* When we do generic sharing we let type variables stand for reference/primitive types. */
1704 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) &&
1705 (!type->data.generic_param->gshared_constraint || type->data.generic_param->gshared_constraint->type == MONO_TYPE_OBJECT))
1706 return &mono_defaults.object_class->byval_arg;
1711 class_has_references (MonoClass *klass)
1713 mono_class_init_sizes (klass);
1716 * has_references is not set if this is called recursively, but this is not a problem since this is only used
1717 * during field layout, and instance fields are initialized before static fields, and instance fields can't
1720 return klass->has_references;
1724 type_has_references (MonoClass *klass, MonoType *ftype)
1726 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (klass, ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && class_has_references (mono_class_from_mono_type (ftype)))))
1728 if (!ftype->byref && (ftype->type == MONO_TYPE_VAR || ftype->type == MONO_TYPE_MVAR)) {
1729 MonoGenericParam *gparam = ftype->data.generic_param;
1731 if (gparam->gshared_constraint)
1732 return class_has_references (mono_class_from_mono_type (gparam->gshared_constraint));
1738 * mono_class_layout_fields:
1740 * @base_instance_size: base instance size
1743 * This contains the common code for computing the layout of classes and sizes.
1744 * This should only be called from mono_class_setup_fields () and
1745 * typebuilder_setup_fields ().
1747 * LOCKING: Acquires the loader lock
1750 mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_size, gboolean sre)
1753 const int top = klass->field.count;
1754 guint32 layout = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK;
1755 guint32 pass, passes, real_size;
1756 gboolean gc_aware_layout = FALSE;
1757 gboolean has_static_fields = FALSE;
1758 gboolean has_references = FALSE;
1759 gboolean has_static_refs = FALSE;
1760 MonoClassField *field;
1762 int instance_size = base_instance_size;
1763 int class_size, min_align;
1767 * We want to avoid doing complicated work inside locks, so we compute all the required
1768 * information and write it to @klass inside a lock.
1770 if (klass->fields_inited)
1773 if ((packing_size & 0xffffff00) != 0) {
1774 mono_class_set_type_load_failure (klass, "Could not load struct '%s' with packing size %d >= 256", klass->name, packing_size);
1778 if (klass->parent) {
1779 min_align = klass->parent->min_align;
1780 /* we use | since it may have been set already */
1781 has_references = klass->has_references | klass->parent->has_references;
1785 /* We can't really enable 16 bytes alignment until the GC supports it.
1786 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1787 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1788 Bug #506144 is an example of this issue.
1790 if (klass->simd_type)
1795 * When we do generic sharing we need to have layout
1796 * information for open generic classes (either with a generic
1797 * context containing type variables or with a generic
1798 * container), so we don't return in that case anymore.
1801 if (klass->enumtype) {
1802 for (i = 0; i < top; i++) {
1803 field = &klass->fields [i];
1804 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1805 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
1810 if (!mono_class_enum_basetype (klass)) {
1811 mono_class_set_type_load_failure (klass, "The enumeration's base type is invalid.");
1817 * Enable GC aware auto layout: in this mode, reference
1818 * fields are grouped together inside objects, increasing collector
1820 * Requires that all classes whose layout is known to native code be annotated
1821 * with [StructLayout (LayoutKind.Sequential)]
1822 * Value types have gc_aware_layout disabled by default, as per
1823 * what the default is for other runtimes.
1825 /* corlib is missing [StructLayout] directives in many places */
1826 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1827 if (!klass->valuetype)
1828 gc_aware_layout = TRUE;
1831 /* Compute klass->blittable */
1834 blittable = klass->parent->blittable;
1835 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(mono_is_corlib_image (klass->image) && !strcmp (klass->name_space, "System") && !strcmp (klass->name, "ValueType")) && top)
1837 for (i = 0; i < top; i++) {
1838 field = &klass->fields [i];
1840 if (mono_field_is_deleted (field))
1842 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1845 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1848 MonoClass *field_class = mono_class_from_mono_type (field->type);
1850 mono_class_setup_fields (field_class);
1851 if (mono_class_has_failure (field_class)) {
1852 MonoError field_error;
1853 mono_error_init (&field_error);
1854 mono_error_set_for_class_failure (&field_error, field_class);
1855 mono_class_set_type_load_failure (klass, "Could not set up field '%s' due to: %s", field->name, mono_error_get_message (&field_error));
1856 mono_error_cleanup (&field_error);
1860 if (!field_class || !field_class->blittable)
1864 if (klass->enumtype)
1865 blittable = klass->element_class->blittable;
1867 if (mono_class_has_failure (klass))
1869 if (klass == mono_defaults.string_class)
1872 /* Compute klass->has_references */
1874 * Process non-static fields first, since static fields might recursively
1875 * refer to the class itself.
1877 for (i = 0; i < top; i++) {
1880 field = &klass->fields [i];
1882 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1883 ftype = mono_type_get_underlying_type (field->type);
1884 ftype = mono_type_get_basic_type_from_generic (ftype);
1885 if (type_has_references (klass, ftype))
1886 has_references = TRUE;
1891 * Compute field layout and total size (not considering static fields)
1893 field_offsets = g_new0 (int, top);
1895 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1896 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1897 if (gc_aware_layout)
1902 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1905 if (klass->parent) {
1906 mono_class_setup_fields (klass->parent);
1907 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Cannot initialize parent class"))
1909 real_size = klass->parent->instance_size;
1911 real_size = sizeof (MonoObject);
1914 for (pass = 0; pass < passes; ++pass) {
1915 for (i = 0; i < top; i++){
1920 field = &klass->fields [i];
1922 if (mono_field_is_deleted (field))
1924 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1927 ftype = mono_type_get_underlying_type (field->type);
1928 ftype = mono_type_get_basic_type_from_generic (ftype);
1929 if (gc_aware_layout) {
1930 if (type_has_references (klass, ftype)) {
1939 if ((top == 1) && (instance_size == sizeof (MonoObject)) &&
1940 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1941 /* This field is a hack inserted by MCS to empty structures */
1945 size = mono_type_size (field->type, &align);
1947 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1948 align = packing_size ? MIN (packing_size, align): align;
1949 /* if the field has managed references, we need to force-align it
1952 if (type_has_references (klass, ftype))
1953 align = MAX (align, sizeof (gpointer));
1955 min_align = MAX (align, min_align);
1956 field_offsets [i] = real_size;
1958 field_offsets [i] += align - 1;
1959 field_offsets [i] &= ~(align - 1);
1961 /*TypeBuilders produce all sort of weird things*/
1962 g_assert (image_is_dynamic (klass->image) || field_offsets [i] > 0);
1963 real_size = field_offsets [i] + size;
1966 instance_size = MAX (real_size, instance_size);
1968 if (instance_size & (min_align - 1)) {
1969 instance_size += min_align - 1;
1970 instance_size &= ~(min_align - 1);
1974 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
1978 for (i = 0; i < top; i++) {
1983 field = &klass->fields [i];
1986 * There must be info about all the fields in a type if it
1987 * uses explicit layout.
1989 if (mono_field_is_deleted (field))
1991 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1994 size = mono_type_size (field->type, &align);
1995 align = packing_size ? MIN (packing_size, align): align;
1996 min_align = MAX (align, min_align);
1999 /* Already set by typebuilder_setup_fields () */
2000 field_offsets [i] = field->offset + sizeof (MonoObject);
2002 int idx = klass->field.first + i;
2004 mono_metadata_field_info (klass->image, idx, &offset, NULL, NULL);
2005 field_offsets [i] = offset + sizeof (MonoObject);
2007 ftype = mono_type_get_underlying_type (field->type);
2008 ftype = mono_type_get_basic_type_from_generic (ftype);
2009 if (type_has_references (klass, ftype)) {
2010 if (field_offsets [i] % sizeof (gpointer)) {
2011 mono_class_set_type_load_failure (klass, "Reference typed field '%s' has explicit offset that is not pointer-size aligned.", field->name);
2018 real_size = MAX (real_size, size + field_offsets [i]);
2021 if (klass->has_references) {
2022 ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
2024 /* Check for overlapping reference and non-reference fields */
2025 for (i = 0; i < top; i++) {
2028 field = &klass->fields [i];
2030 if (mono_field_is_deleted (field))
2032 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2034 ftype = mono_type_get_underlying_type (field->type);
2035 if (MONO_TYPE_IS_REFERENCE (ftype))
2036 ref_bitmap [field_offsets [i] / sizeof (gpointer)] = 1;
2038 for (i = 0; i < top; i++) {
2039 field = &klass->fields [i];
2041 if (mono_field_is_deleted (field))
2043 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2046 // FIXME: Too much code does this
2048 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field_offsets [i] / sizeof (gpointer)]) {
2049 mono_class_set_type_load_failure (klass, "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_offsets [i]);
2053 g_free (ref_bitmap);
2056 instance_size = MAX (real_size, instance_size);
2057 if (instance_size & (min_align - 1)) {
2058 instance_size += min_align - 1;
2059 instance_size &= ~(min_align - 1);
2065 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2067 * This leads to all kinds of problems with nested structs, so only
2068 * enable it when a MONO_DEBUG property is set.
2070 * For small structs, set min_align to at least the struct size to improve
2071 * performance, and since the JIT memset/memcpy code assumes this and generates
2072 * unaligned accesses otherwise. See #78990 for a testcase.
2074 if (mono_align_small_structs && top) {
2075 if (instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2076 min_align = MAX (min_align, instance_size - sizeof (MonoObject));
2080 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR)
2081 instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
2082 else if (klass->byval_arg.type == MONO_TYPE_PTR)
2083 instance_size = sizeof (MonoObject) + sizeof (gpointer);
2085 /* Publish the data */
2086 mono_loader_lock ();
2087 if (klass->instance_size && !klass->image->dynamic) {
2088 /* Might be already set using cached info */
2089 g_assert (klass->instance_size == instance_size);
2091 klass->instance_size = instance_size;
2093 klass->blittable = blittable;
2094 klass->has_references = has_references;
2095 klass->packing_size = packing_size;
2096 klass->min_align = min_align;
2097 for (i = 0; i < top; ++i) {
2098 field = &klass->fields [i];
2099 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
2100 klass->fields [i].offset = field_offsets [i];
2103 mono_memory_barrier ();
2104 klass->size_inited = 1;
2105 mono_loader_unlock ();
2108 * Compute static field layout and size
2109 * Static fields can reference the class itself, so this has to be
2110 * done after instance_size etc. are initialized.
2113 for (i = 0; i < top; i++) {
2117 field = &klass->fields [i];
2119 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2121 if (mono_field_is_deleted (field))
2124 if (mono_type_has_exceptions (field->type)) {
2125 mono_class_set_type_load_failure (klass, "Field '%s' has an invalid type.", field->name);
2129 has_static_fields = TRUE;
2131 size = mono_type_size (field->type, &align);
2132 field_offsets [i] = class_size;
2133 /*align is always non-zero here*/
2134 field_offsets [i] += align - 1;
2135 field_offsets [i] &= ~(align - 1);
2136 class_size = field_offsets [i] + size;
2139 if (has_static_fields && class_size == 0)
2140 /* Simplify code which depends on class_size != 0 if the class has static fields */
2143 /* Compute klass->has_static_refs */
2144 has_static_refs = FALSE;
2145 for (i = 0; i < top; i++) {
2148 field = &klass->fields [i];
2150 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
2151 ftype = mono_type_get_underlying_type (field->type);
2152 ftype = mono_type_get_basic_type_from_generic (ftype);
2153 if (type_has_references (klass, ftype))
2154 has_static_refs = TRUE;
2158 /*valuetypes can't be neither bigger than 1Mb or empty. */
2159 if (klass->valuetype && (klass->instance_size <= 0 || klass->instance_size > (0x100000 + sizeof (MonoObject))))
2160 mono_class_set_type_load_failure (klass, "Value type instance size (%d) cannot be zero, negative, or bigger than 1Mb", klass->instance_size);
2162 /* Publish the data */
2163 mono_loader_lock ();
2165 klass->sizes.class_size = class_size;
2166 klass->has_static_refs = has_static_refs;
2167 for (i = 0; i < top; ++i) {
2168 field = &klass->fields [i];
2170 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2171 field->offset = field_offsets [i];
2174 mono_memory_barrier ();
2175 klass->fields_inited = 1;
2176 mono_loader_unlock ();
2178 g_free (field_offsets);
2182 create_array_method (MonoClass *klass, const char *name, MonoMethodSignature *sig)
2186 method = (MonoMethod *) mono_image_alloc0 (klass->image, sizeof (MonoMethodPInvoke));
2187 method->klass = klass;
2188 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2189 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2190 method->signature = sig;
2191 method->name = name;
2194 if (name [0] == '.') {
2195 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2197 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2203 * mono_class_setup_methods:
2206 * Initializes the 'methods' array in CLASS.
2207 * Calling this method should be avoided if possible since it allocates a lot
2208 * of long-living MonoMethod structures.
2209 * Methods belonging to an interface are assigned a sequential slot starting
2212 * On failure this function sets klass->has_failure and stores a MonoErrorBoxed with details
2215 mono_class_setup_methods (MonoClass *klass)
2218 MonoMethod **methods;
2223 if (mono_class_is_ginst (klass)) {
2225 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2227 mono_class_init (gklass);
2228 if (!mono_class_has_failure (gklass))
2229 mono_class_setup_methods (gklass);
2230 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2233 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2234 count = gklass->method.count;
2235 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * (count + 1));
2237 for (i = 0; i < count; i++) {
2238 methods [i] = mono_class_inflate_generic_method_full_checked (
2239 gklass->methods [i], klass, mono_class_get_context (klass), &error);
2240 if (!mono_error_ok (&error)) {
2241 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2242 mono_class_set_type_load_failure (klass, "Could not inflate method %s due to %s", method, mono_error_get_message (&error));
2245 mono_error_cleanup (&error);
2249 } else if (klass->rank) {
2251 MonoMethod *amethod;
2252 MonoMethodSignature *sig;
2253 int count_generic = 0, first_generic = 0;
2255 gboolean jagged_ctor = FALSE;
2257 count = 3 + (klass->rank > 1? 2: 1);
2259 mono_class_setup_interfaces (klass, &error);
2260 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2262 if (klass->rank == 1 && klass->element_class->rank) {
2264 klass->method.count ++;
2267 if (klass->interface_count) {
2268 count_generic = generic_array_methods (klass);
2269 first_generic = count;
2270 count += klass->interface_count * count_generic;
2273 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * count);
2275 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2276 sig->ret = &mono_defaults.void_class->byval_arg;
2277 sig->pinvoke = TRUE;
2278 sig->hasthis = TRUE;
2279 for (i = 0; i < klass->rank; ++i)
2280 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2282 amethod = create_array_method (klass, ".ctor", sig);
2283 methods [method_num++] = amethod;
2284 if (klass->rank > 1) {
2285 sig = mono_metadata_signature_alloc (klass->image, klass->rank * 2);
2286 sig->ret = &mono_defaults.void_class->byval_arg;
2287 sig->pinvoke = TRUE;
2288 sig->hasthis = TRUE;
2289 for (i = 0; i < klass->rank * 2; ++i)
2290 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2292 amethod = create_array_method (klass, ".ctor", sig);
2293 methods [method_num++] = amethod;
2297 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2298 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2299 sig->ret = &mono_defaults.void_class->byval_arg;
2300 sig->pinvoke = TRUE;
2301 sig->hasthis = TRUE;
2302 for (i = 0; i < klass->rank + 1; ++i)
2303 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2304 amethod = create_array_method (klass, ".ctor", sig);
2305 methods [method_num++] = amethod;
2308 /* element Get (idx11, [idx2, ...]) */
2309 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2310 sig->ret = &klass->element_class->byval_arg;
2311 sig->pinvoke = TRUE;
2312 sig->hasthis = TRUE;
2313 for (i = 0; i < klass->rank; ++i)
2314 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2315 amethod = create_array_method (klass, "Get", sig);
2316 methods [method_num++] = amethod;
2317 /* element& Address (idx11, [idx2, ...]) */
2318 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2319 sig->ret = &klass->element_class->this_arg;
2320 sig->pinvoke = TRUE;
2321 sig->hasthis = TRUE;
2322 for (i = 0; i < klass->rank; ++i)
2323 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2324 amethod = create_array_method (klass, "Address", sig);
2325 methods [method_num++] = amethod;
2326 /* void Set (idx11, [idx2, ...], element) */
2327 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2328 sig->ret = &mono_defaults.void_class->byval_arg;
2329 sig->pinvoke = TRUE;
2330 sig->hasthis = TRUE;
2331 for (i = 0; i < klass->rank; ++i)
2332 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2333 sig->params [i] = &klass->element_class->byval_arg;
2334 amethod = create_array_method (klass, "Set", sig);
2335 methods [method_num++] = amethod;
2337 for (i = 0; i < klass->interface_count; i++)
2338 setup_generic_array_ifaces (klass, klass->interfaces [i], methods, first_generic + i * count_generic);
2342 count = klass->method.count;
2343 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * count);
2344 for (i = 0; i < count; ++i) {
2345 int idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_METHOD, klass->method.first + i + 1);
2346 methods [i] = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | idx, klass, NULL, &error);
2348 mono_class_set_type_load_failure (klass, "Could not load method %d due to %s", i, mono_error_get_message (&error));
2349 mono_error_cleanup (&error);
2354 if (MONO_CLASS_IS_INTERFACE (klass)) {
2356 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2357 for (i = 0; i < count; ++i) {
2358 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2359 methods [i]->slot = slot++;
2363 mono_image_lock (klass->image);
2365 if (!klass->methods) {
2366 klass->method.count = count;
2368 /* Needed because of the double-checking locking pattern */
2369 mono_memory_barrier ();
2371 klass->methods = methods;
2374 mono_image_unlock (klass->image);
2378 * mono_class_get_method_by_index:
2380 * Returns klass->methods [index], initializing klass->methods if neccesary.
2382 * LOCKING: Acquires the loader lock.
2385 mono_class_get_method_by_index (MonoClass *klass, int index)
2389 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
2390 /* Avoid calling setup_methods () if possible */
2391 if (gklass && !klass->methods) {
2394 m = mono_class_inflate_generic_method_full_checked (
2395 gklass->container_class->methods [index], klass, mono_class_get_context (klass), &error);
2396 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2398 * If setup_methods () is called later for this class, no duplicates are created,
2399 * since inflate_generic_method guarantees that only one instance of a method
2400 * is created for each context.
2403 mono_class_setup_methods (klass);
2404 g_assert (m == klass->methods [index]);
2408 mono_class_setup_methods (klass);
2409 if (mono_class_has_failure (klass)) /*FIXME do proper error handling*/
2411 g_assert (index >= 0 && index < klass->method.count);
2412 return klass->methods [index];
2417 * mono_class_get_inflated_method:
2419 * Given an inflated class CLASS and a method METHOD which should be a method of
2420 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2423 mono_class_get_inflated_method (MonoClass *klass, MonoMethod *method)
2425 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2428 g_assert (method->klass == gklass);
2430 mono_class_setup_methods (gklass);
2431 g_assert (!mono_class_has_failure (gklass)); /*FIXME do proper error handling*/
2433 for (i = 0; i < gklass->method.count; ++i) {
2434 if (gklass->methods [i] == method) {
2435 if (klass->methods) {
2436 return klass->methods [i];
2439 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], klass, mono_class_get_context (klass), &error);
2440 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2450 * mono_class_get_vtable_entry:
2452 * Returns klass->vtable [offset], computing it if neccesary. Returns NULL on failure.
2453 * LOCKING: Acquires the loader lock.
2456 mono_class_get_vtable_entry (MonoClass *klass, int offset)
2460 if (klass->rank == 1) {
2462 * szarrays do not overwrite any methods of Array, so we can avoid
2463 * initializing their vtables in some cases.
2465 mono_class_setup_vtable (klass->parent);
2466 if (offset < klass->parent->vtable_size)
2467 return klass->parent->vtable [offset];
2470 if (mono_class_is_ginst (klass)) {
2472 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2473 mono_class_setup_vtable (gklass);
2474 m = gklass->vtable [offset];
2476 m = mono_class_inflate_generic_method_full_checked (m, klass, mono_class_get_context (klass), &error);
2477 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2479 mono_class_setup_vtable (klass);
2480 if (mono_class_has_failure (klass))
2482 m = klass->vtable [offset];
2489 * mono_class_get_vtable_size:
2491 * Return the vtable size for KLASS.
2494 mono_class_get_vtable_size (MonoClass *klass)
2496 mono_class_setup_vtable (klass);
2498 return klass->vtable_size;
2502 * mono_class_setup_properties:
2504 * Initialize klass->ext.property and klass->ext.properties.
2506 * This method can fail the class.
2509 mono_class_setup_properties (MonoClass *klass)
2511 guint startm, endm, i, j;
2512 guint32 cols [MONO_PROPERTY_SIZE];
2513 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2514 MonoProperty *properties;
2518 if (klass->ext && klass->ext->properties)
2521 if (mono_class_is_ginst (klass)) {
2522 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2524 mono_class_init (gklass);
2525 mono_class_setup_properties (gklass);
2526 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "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 (mono_class_is_ginst (klass)) {
2653 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2654 MonoGenericContext *context = NULL;
2656 mono_class_setup_events (gklass);
2657 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2660 first = gklass->ext->event.first;
2661 count = gklass->ext->event.count;
2663 events = mono_class_new0 (klass, MonoEvent, count);
2666 context = mono_class_get_context (klass);
2668 for (i = 0; i < count; i++) {
2670 MonoEvent *event = &events [i];
2671 MonoEvent *gevent = &gklass->ext->events [i];
2673 mono_error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2675 event->parent = klass;
2676 event->name = gevent->name;
2677 event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, klass, context, &error) : NULL;
2678 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2679 event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, klass, context, &error) : NULL;
2680 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2681 event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, klass, context, &error) : NULL;
2682 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2684 #ifndef MONO_SMALL_CONFIG
2685 event->other = gevent->other ? inflate_method_listz (gevent->other, klass, context) : NULL;
2687 event->attrs = gevent->attrs;
2690 first = mono_metadata_events_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2691 count = last - first;
2694 mono_class_setup_methods (klass);
2695 if (mono_class_has_failure (klass)) {
2700 events = (MonoEvent *)mono_class_alloc0 (klass, sizeof (MonoEvent) * count);
2701 for (i = first; i < last; ++i) {
2702 MonoEvent *event = &events [i - first];
2704 mono_metadata_decode_table_row (klass->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2705 event->parent = klass;
2706 event->attrs = cols [MONO_EVENT_FLAGS];
2707 event->name = mono_metadata_string_heap (klass->image, cols [MONO_EVENT_NAME]);
2709 startm = mono_metadata_methods_from_event (klass->image, i, &endm);
2710 for (j = startm; j < endm; ++j) {
2713 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2715 if (klass->image->uncompressed_metadata) {
2717 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2718 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2719 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2721 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - klass->method.first];
2724 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2725 case METHOD_SEMANTIC_ADD_ON:
2726 event->add = method;
2728 case METHOD_SEMANTIC_REMOVE_ON:
2729 event->remove = method;
2731 case METHOD_SEMANTIC_FIRE:
2732 event->raise = method;
2734 case METHOD_SEMANTIC_OTHER: {
2735 #ifndef MONO_SMALL_CONFIG
2738 if (event->other == NULL) {
2739 event->other = g_new0 (MonoMethod*, 2);
2741 while (event->other [n])
2743 event->other = (MonoMethod **)g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2745 event->other [n] = method;
2746 /* NULL terminated */
2747 event->other [n + 1] = NULL;
2758 mono_class_alloc_ext (klass);
2760 mono_image_lock (klass->image);
2762 if (klass->ext->events) {
2763 mono_image_unlock (klass->image);
2767 klass->ext->event.first = first;
2768 klass->ext->event.count = count;
2770 /* Flush any pending writes as we do double checked locking on klass->ext.events */
2771 mono_memory_barrier ();
2773 /* Leave this assignment as the last op in the function */
2774 klass->ext->events = events;
2776 mono_image_unlock (klass->image);
2780 * Global pool of interface IDs, represented as a bitset.
2781 * LOCKING: Protected by the classes lock.
2783 static MonoBitSet *global_interface_bitset = NULL;
2786 * mono_unload_interface_ids:
2787 * @bitset: bit set of interface IDs
2789 * When an image is unloaded, the interface IDs associated with
2790 * the image are put back in the global pool of IDs so the numbers
2794 mono_unload_interface_ids (MonoBitSet *bitset)
2797 mono_bitset_sub (global_interface_bitset, bitset);
2802 mono_unload_interface_id (MonoClass *klass)
2804 if (global_interface_bitset && klass->interface_id) {
2806 mono_bitset_clear (global_interface_bitset, klass->interface_id);
2812 * mono_get_unique_iid:
2815 * Assign a unique integer ID to the interface represented by @class.
2816 * The ID will positive and as small as possible.
2817 * LOCKING: Acquires the classes lock.
2818 * Returns: The new ID.
2821 mono_get_unique_iid (MonoClass *klass)
2825 g_assert (MONO_CLASS_IS_INTERFACE (klass));
2829 if (!global_interface_bitset) {
2830 global_interface_bitset = mono_bitset_new (128, 0);
2833 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2835 int old_size = mono_bitset_size (global_interface_bitset);
2836 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2837 mono_bitset_free (global_interface_bitset);
2838 global_interface_bitset = new_set;
2841 mono_bitset_set (global_interface_bitset, iid);
2842 /* set the bit also in the per-image set */
2843 if (!mono_class_is_ginst (klass)) {
2844 if (klass->image->interface_bitset) {
2845 if (iid >= mono_bitset_size (klass->image->interface_bitset)) {
2846 MonoBitSet *new_set = mono_bitset_clone (klass->image->interface_bitset, iid + 1);
2847 mono_bitset_free (klass->image->interface_bitset);
2848 klass->image->interface_bitset = new_set;
2851 klass->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2853 mono_bitset_set (klass->image->interface_bitset, iid);
2858 #ifndef MONO_SMALL_CONFIG
2859 if (mono_print_vtable) {
2861 char *type_name = mono_type_full_name (&klass->byval_arg);
2862 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
2863 if (gklass && !gklass->context.class_inst->is_open) {
2864 generic_id = gklass->context.class_inst->id;
2865 g_assert (generic_id != 0);
2869 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, klass->image->name, type_name, generic_id);
2874 g_assert (iid <= 65535);
2879 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2884 mono_class_setup_interfaces (klass, error);
2885 return_if_nok (error);
2887 for (i = 0; i < klass->interface_count; i++) {
2888 ic = klass->interfaces [i];
2891 *res = g_ptr_array_new ();
2892 g_ptr_array_add (*res, ic);
2893 mono_class_init (ic);
2894 if (mono_class_has_failure (ic)) {
2895 mono_error_set_type_load_class (error, ic, "Error Loading class");
2899 collect_implemented_interfaces_aux (ic, res, error);
2900 return_if_nok (error);
2905 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2907 GPtrArray *res = NULL;
2909 collect_implemented_interfaces_aux (klass, &res, error);
2910 if (!mono_error_ok (error)) {
2912 g_ptr_array_free (res, TRUE);
2919 compare_interface_ids (const void *p_key, const void *p_element) {
2920 const MonoClass *key = (const MonoClass *)p_key;
2921 const MonoClass *element = *(const MonoClass **)p_element;
2923 return (key->interface_id - element->interface_id);
2926 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2928 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2929 MonoClass **result = (MonoClass **)mono_binary_search (
2931 klass->interfaces_packed,
2932 klass->interface_offsets_count,
2933 sizeof (MonoClass *),
2934 compare_interface_ids);
2936 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2943 * mono_class_interface_offset_with_variance:
2945 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2946 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2948 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2950 * FIXME figure out MS disambiguation rules and fix this function.
2953 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2954 int i = mono_class_interface_offset (klass, itf);
2955 *non_exact_match = FALSE;
2959 if (!mono_class_has_variant_generic_params (itf))
2962 for (i = 0; i < klass->interface_offsets_count; i++) {
2963 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2964 *non_exact_match = TRUE;
2965 return klass->interface_offsets_packed [i];
2973 print_implemented_interfaces (MonoClass *klass) {
2976 GPtrArray *ifaces = NULL;
2978 int ancestor_level = 0;
2980 name = mono_type_get_full_name (klass);
2981 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2984 for (i = 0; i < klass->interface_offsets_count; i++)
2985 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2986 klass->interfaces_packed [i]->interface_id,
2987 klass->interface_offsets_packed [i],
2988 klass->interfaces_packed [i]->method.count,
2989 klass->interfaces_packed [i]->name_space,
2990 klass->interfaces_packed [i]->name );
2991 printf ("Interface flags: ");
2992 for (i = 0; i <= klass->max_interface_id; i++)
2993 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2994 printf ("(%d,T)", i);
2996 printf ("(%d,F)", i);
2998 printf ("Dump interface flags:");
2999 #ifdef COMPRESSED_INTERFACE_BITMAP
3001 const uint8_t* p = klass->interface_bitmap;
3002 i = klass->max_interface_id;
3004 printf (" %d x 00 %02X", p [0], p [1]);
3010 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
3011 printf (" %02X", klass->interface_bitmap [i]);
3014 while (klass != NULL) {
3015 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
3016 ifaces = mono_class_get_implemented_interfaces (klass, &error);
3017 if (!mono_error_ok (&error)) {
3018 printf (" Type failed due to %s\n", mono_error_get_message (&error));
3019 mono_error_cleanup (&error);
3020 } else if (ifaces) {
3021 for (i = 0; i < ifaces->len; i++) {
3022 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3023 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
3024 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3026 mono_class_interface_offset (klass, ic),
3031 g_ptr_array_free (ifaces, TRUE);
3034 klass = klass->parent;
3039 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
3042 args [0] = &arg0->byval_arg;
3044 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
3048 array_class_get_if_rank (MonoClass *klass, guint rank)
3050 return rank ? mono_array_class_get (klass, rank) : klass;
3054 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
3056 valuetype_types [0] = eclass;
3057 if (eclass == mono_defaults.int16_class)
3058 valuetype_types [1] = mono_defaults.uint16_class;
3059 else if (eclass == mono_defaults.uint16_class)
3060 valuetype_types [1] = mono_defaults.int16_class;
3061 else if (eclass == mono_defaults.int32_class)
3062 valuetype_types [1] = mono_defaults.uint32_class;
3063 else if (eclass == mono_defaults.uint32_class)
3064 valuetype_types [1] = mono_defaults.int32_class;
3065 else if (eclass == mono_defaults.int64_class)
3066 valuetype_types [1] = mono_defaults.uint64_class;
3067 else if (eclass == mono_defaults.uint64_class)
3068 valuetype_types [1] = mono_defaults.int64_class;
3069 else if (eclass == mono_defaults.byte_class)
3070 valuetype_types [1] = mono_defaults.sbyte_class;
3071 else if (eclass == mono_defaults.sbyte_class)
3072 valuetype_types [1] = mono_defaults.byte_class;
3073 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
3074 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
3077 static GENERATE_GET_CLASS_WITH_CACHE (generic_icollection, System.Collections.Generic, ICollection`1)
3078 static GENERATE_GET_CLASS_WITH_CACHE (generic_ienumerable, System.Collections.Generic, IEnumerable`1)
3079 static GENERATE_GET_CLASS_WITH_CACHE (generic_ienumerator, System.Collections.Generic, IEnumerator`1)
3080 static GENERATE_GET_CLASS_WITH_CACHE (generic_ireadonlylist, System.Collections.Generic, IReadOnlyList`1)
3081 static GENERATE_GET_CLASS_WITH_CACHE (generic_ireadonlycollection, System.Collections.Generic, IReadOnlyCollection`1)
3083 /* this won't be needed once bug #325495 is completely fixed
3084 * though we'll need something similar to know which interfaces to allow
3085 * in arrays when they'll be lazyly created
3087 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
3088 * MS returns diferrent types based on which instance is called. For example:
3089 * object obj = new byte[10][];
3090 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
3091 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
3094 * Fixing this should kill quite some code, save some bits and improve compatibility.
3097 get_implicit_generic_array_interfaces (MonoClass *klass, int *num, int *is_enumerator)
3099 MonoClass *eclass = klass->element_class;
3100 MonoClass* generic_icollection_class;
3101 MonoClass* generic_ienumerable_class;
3102 MonoClass* generic_ienumerator_class;
3103 MonoClass* generic_ireadonlylist_class;
3104 MonoClass* generic_ireadonlycollection_class;
3105 MonoClass *valuetype_types[2] = { NULL, NULL };
3106 MonoClass **interfaces = NULL;
3107 int i, nifaces, interface_count, real_count, original_rank;
3109 gboolean internal_enumerator;
3110 gboolean eclass_is_valuetype;
3112 if (!mono_defaults.generic_ilist_class) {
3116 internal_enumerator = FALSE;
3117 eclass_is_valuetype = FALSE;
3118 original_rank = eclass->rank;
3119 if (klass->byval_arg.type != MONO_TYPE_SZARRAY) {
3120 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
3121 if (gklass && klass->nested_in == mono_defaults.array_class && strcmp (klass->name, "InternalEnumerator`1") == 0) {
3123 * For a Enumerator<T[]> we need to get the list of interfaces for T.
3125 eclass = mono_class_from_mono_type (gklass->context.class_inst->type_argv [0]);
3126 original_rank = eclass->rank;
3128 eclass = eclass->element_class;
3129 internal_enumerator = TRUE;
3130 *is_enumerator = TRUE;
3138 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
3139 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
3141 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
3143 generic_icollection_class = mono_class_get_generic_icollection_class ();
3144 generic_ienumerable_class = mono_class_get_generic_ienumerable_class ();
3145 generic_ienumerator_class = mono_class_get_generic_ienumerator_class ();
3146 generic_ireadonlylist_class = mono_class_get_generic_ireadonlylist_class ();
3147 generic_ireadonlycollection_class = mono_class_get_generic_ireadonlycollection_class ();
3149 mono_class_init (eclass);
3152 * Arrays in 2.0 need to implement a number of generic interfaces
3153 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
3154 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
3155 * We collect the types needed to build the
3156 * instantiations in interfaces at intervals of 3/5, because 3/5 are
3157 * the generic interfaces needed to implement.
3159 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
3160 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
3162 if (eclass->valuetype) {
3163 nifaces = generic_ireadonlylist_class ? 5 : 3;
3164 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
3166 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
3167 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
3168 if (internal_enumerator) {
3170 if (valuetype_types [1])
3174 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3175 interfaces [0] = valuetype_types [0];
3176 if (valuetype_types [1])
3177 interfaces [nifaces] = valuetype_types [1];
3179 eclass_is_valuetype = TRUE;
3182 int idepth = eclass->idepth;
3183 if (!internal_enumerator)
3185 nifaces = generic_ireadonlylist_class ? 2 : 3;
3187 // FIXME: This doesn't seem to work/required for generic params
3188 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
3189 mono_class_setup_interface_offsets (eclass);
3191 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
3192 /* we add object for interfaces and the supertypes for the other
3193 * types. The last of the supertypes is the element class itself which we
3194 * already created the explicit interfaces for (so we include it for IEnumerator
3195 * and exclude it for arrays).
3197 if (MONO_CLASS_IS_INTERFACE (eclass))
3200 interface_count += idepth;
3201 if (eclass->rank && eclass->element_class->valuetype) {
3202 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3203 if (valuetype_types [1])
3206 /* IList, ICollection, IEnumerable, IReadOnlyList */
3207 interface_count *= nifaces;
3208 real_count = interface_count;
3209 if (internal_enumerator) {
3210 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3211 if (valuetype_types [1])
3214 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3215 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3216 interfaces [0] = mono_defaults.object_class;
3220 for (i = 0; i < idepth; i++) {
3221 mono_class_init (eclass->supertypes [i]);
3222 interfaces [j] = eclass->supertypes [i];
3226 if (all_interfaces) {
3227 for (i = 0; i < eclass->interface_offsets_count; i++) {
3228 interfaces [j] = eclass->interfaces_packed [i];
3232 for (i = 0; i < eclass->interface_count; i++) {
3233 interfaces [j] = eclass->interfaces [i];
3237 if (valuetype_types [1]) {
3238 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3243 /* instantiate the generic interfaces */
3244 for (i = 0; i < interface_count; i += nifaces) {
3245 MonoClass *iface = interfaces [i];
3247 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3248 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3250 if (eclass->valuetype) {
3251 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3252 if (generic_ireadonlylist_class) {
3253 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3254 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3257 if (!generic_ireadonlylist_class)
3258 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3261 if (internal_enumerator) {
3263 /* instantiate IEnumerator<iface> */
3264 for (i = 0; i < interface_count; i++) {
3265 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3267 j = interface_count;
3268 if (!eclass_is_valuetype) {
3269 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3270 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3273 for (i = 0; i < eclass->idepth; i++) {
3274 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3278 for (i = 0; i < eclass->interface_offsets_count; i++) {
3279 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3283 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3285 if (valuetype_types [1])
3286 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3290 char *type_name = mono_type_get_name_full (&klass->byval_arg, 0);
3291 for (i = 0; i < real_count; ++i) {
3292 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3293 g_print ("%s implements %s\n", type_name, name);
3304 find_array_interface (MonoClass *klass, const char *name)
3307 for (i = 0; i < klass->interface_count; ++i) {
3308 if (strcmp (klass->interfaces [i]->name, name) == 0)
3315 * Return the number of virtual methods.
3316 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3317 * Return -1 on failure.
3318 * FIXME It would be nice if this information could be cached somewhere.
3321 count_virtual_methods (MonoClass *klass)
3325 klass = mono_class_get_generic_type_definition (klass); /*We can find this information by looking at the GTD*/
3327 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
3328 mono_class_setup_methods (klass);
3329 if (mono_class_has_failure (klass))
3332 for (i = 0; i < klass->method.count; ++i) {
3333 flags = klass->methods [i]->flags;
3334 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3338 for (i = 0; i < klass->method.count; ++i) {
3339 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
3341 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3349 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3357 m = (l + num_ifaces) / 2;
3358 if (interfaces_full [m] == ic)
3360 if (l == num_ifaces)
3362 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3371 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3373 int i = find_interface (num_ifaces, interfaces_full, ic);
3375 return interface_offsets_full [i];
3380 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3382 int i = find_interface (num_ifaces, interfaces_full, ic);
3386 interface_offsets_full [i] = offset;
3389 for (i = 0; i < num_ifaces; ++i) {
3390 if (interfaces_full [i]) {
3392 if (interfaces_full [i]->interface_id < ic->interface_id)
3395 while (end < num_ifaces && interfaces_full [end]) end++;
3396 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3397 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3399 interfaces_full [i] = ic;
3400 interface_offsets_full [i] = offset;
3406 #ifdef COMPRESSED_INTERFACE_BITMAP
3409 * Compressed interface bitmap design.
3411 * Interface bitmaps take a large amount of memory, because their size is
3412 * linear with the maximum interface id assigned in the process (each interface
3413 * is assigned a unique id as it is loaded). The number of interface classes
3414 * is high because of the many implicit interfaces implemented by arrays (we'll
3415 * need to lazy-load them in the future).
3416 * Most classes implement a very small number of interfaces, so the bitmap is
3417 * sparse. This bitmap needs to be checked by interface casts, so access to the
3418 * needed bit must be fast and doable with few jit instructions.
3420 * The current compression format is as follows:
3421 * *) it is a sequence of one or more two-byte elements
3422 * *) the first byte in the element is the count of empty bitmap bytes
3423 * at the current bitmap position
3424 * *) the second byte in the element is an actual bitmap byte at the current
3427 * As an example, the following compressed bitmap bytes:
3428 * 0x07 0x01 0x00 0x7
3429 * correspond to the following bitmap:
3430 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3432 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3433 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3434 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3438 * mono_compress_bitmap:
3439 * @dest: destination buffer
3440 * @bitmap: bitmap buffer
3441 * @size: size of @bitmap in bytes
3443 * This is a mono internal function.
3444 * The @bitmap data is compressed into a format that is small but
3445 * still searchable in few instructions by the JIT and runtime.
3446 * The compressed data is stored in the buffer pointed to by the
3447 * @dest array. Passing a #NULL value for @dest allows to just compute
3448 * the size of the buffer.
3449 * This compression algorithm assumes the bits set in the bitmap are
3450 * few and far between, like in interface bitmaps.
3451 * Returns: The size of the compressed bitmap in bytes.
3454 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3458 const uint8_t *end = bitmap + size;
3459 while (bitmap < end) {
3460 if (*bitmap || numz == 255) {
3484 * mono_class_interface_match:
3485 * @bitmap: a compressed bitmap buffer
3486 * @id: the index to check in the bitmap
3488 * This is a mono internal function.
3489 * Checks if a bit is set in a compressed interface bitmap. @id must
3490 * be already checked for being smaller than the maximum id encoded in the
3493 * Returns: A non-zero value if bit @id is set in the bitmap @bitmap,
3497 mono_class_interface_match (const uint8_t *bitmap, int id)
3500 id -= bitmap [0] * 8;
3504 return bitmap [1] & (1 << id);
3513 * Return -1 on failure and set klass->has_failure and store a MonoErrorBoxed with the details.
3514 * LOCKING: Acquires the loader lock.
3517 setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite)
3521 int i, j, max_iid, num_ifaces;
3522 MonoClass **interfaces_full = NULL;
3523 int *interface_offsets_full = NULL;
3525 GPtrArray **ifaces_array = NULL;
3526 int interface_offsets_count;
3527 MonoClass **array_interfaces = NULL;
3528 int num_array_interfaces;
3529 int is_enumerator = FALSE;
3531 mono_class_setup_supertypes (klass);
3533 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3534 * implicit interfaces have the property that they are assigned the same slot in the
3535 * vtables for compatible interfaces
3537 array_interfaces = get_implicit_generic_array_interfaces (klass, &num_array_interfaces, &is_enumerator);
3539 /* compute maximum number of slots and maximum interface id */
3541 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3542 ifaces_array = g_new0 (GPtrArray *, klass->idepth);
3543 for (j = 0; j < klass->idepth; j++) {
3544 k = klass->supertypes [j];
3545 num_ifaces += k->interface_count;
3546 for (i = 0; i < k->interface_count; i++) {
3547 ic = k->interfaces [i];
3549 mono_class_init (ic);
3551 if (max_iid < ic->interface_id)
3552 max_iid = ic->interface_id;
3554 ifaces = mono_class_get_implemented_interfaces (k, &error);
3555 if (!mono_error_ok (&error)) {
3556 char *name = mono_type_get_full_name (k);
3557 mono_class_set_type_load_failure (klass, "Error getting the interfaces of %s due to %s", name, mono_error_get_message (&error));
3559 mono_error_cleanup (&error);
3564 num_ifaces += ifaces->len;
3565 for (i = 0; i < ifaces->len; ++i) {
3566 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3567 if (max_iid < ic->interface_id)
3568 max_iid = ic->interface_id;
3570 ifaces_array [j] = ifaces;
3574 for (i = 0; i < num_array_interfaces; ++i) {
3575 ic = array_interfaces [i];
3576 mono_class_init (ic);
3577 if (max_iid < ic->interface_id)
3578 max_iid = ic->interface_id;
3581 if (MONO_CLASS_IS_INTERFACE (klass)) {
3583 if (max_iid < klass->interface_id)
3584 max_iid = klass->interface_id;
3587 /* compute vtable offset for interfaces */
3588 interfaces_full = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3589 interface_offsets_full = (int *)g_malloc (sizeof (int) * num_ifaces);
3591 for (i = 0; i < num_ifaces; i++)
3592 interface_offsets_full [i] = -1;
3594 /* skip the current class */
3595 for (j = 0; j < klass->idepth - 1; j++) {
3596 k = klass->supertypes [j];
3597 ifaces = ifaces_array [j];
3600 for (i = 0; i < ifaces->len; ++i) {
3602 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3604 /*Force the sharing of interface offsets between parent and subtypes.*/
3605 io = mono_class_interface_offset (k, ic);
3607 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3612 g_assert (klass == klass->supertypes [klass->idepth - 1]);
3613 ifaces = ifaces_array [klass->idepth - 1];
3615 for (i = 0; i < ifaces->len; ++i) {
3617 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3618 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3620 count = count_virtual_methods (ic);
3622 char *name = mono_type_get_full_name (ic);
3623 mono_class_set_type_load_failure (klass, "Error calculating interface offset of %s", name);
3632 if (MONO_CLASS_IS_INTERFACE (klass))
3633 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, klass, cur_slot, TRUE);
3635 if (num_array_interfaces) {
3636 if (is_enumerator) {
3637 int ienumerator_idx = find_array_interface (klass, "IEnumerator`1");
3638 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ienumerator_idx]);
3639 g_assert (ienumerator_offset >= 0);
3640 for (i = 0; i < num_array_interfaces; ++i) {
3641 ic = array_interfaces [i];
3642 if (strcmp (ic->name, "IEnumerator`1") == 0)
3643 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3645 g_assert_not_reached ();
3646 /*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);*/
3649 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3650 int ilist_iface_idx = find_array_interface (klass, "IList`1");
3651 MonoClass* ilist_class = klass->interfaces [ilist_iface_idx];
3652 int ireadonlylist_iface_idx = find_array_interface (klass, "IReadOnlyList`1");
3653 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? klass->interfaces [ireadonlylist_iface_idx] : NULL;
3654 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3655 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3656 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3657 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ilist_iface_idx]);
3658 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3659 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3660 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ireadonlylist_iface_idx]) : -1;
3661 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3662 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3663 for (i = 0; i < num_array_interfaces; ++i) {
3665 ic = array_interfaces [i];
3666 if (mono_class_get_generic_class (ic)->container_class == mono_defaults.generic_ilist_class)
3667 offset = ilist_offset;
3668 else if (strcmp (ic->name, "ICollection`1") == 0)
3669 offset = icollection_offset;
3670 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3671 offset = ienumerable_offset;
3672 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3673 offset = ireadonlylist_offset;
3674 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3675 offset = ireadonlycollection_offset;
3677 g_assert_not_reached ();
3678 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3679 /*g_print ("type %s has %s offset at %d (%s)\n", klass->name, ic->name, offset, klass->interfaces [0]->name);*/
3684 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3685 if (interface_offsets_full [i] != -1)
3686 interface_offsets_count ++;
3689 /* Publish the data */
3690 mono_loader_lock ();
3692 klass->max_interface_id = max_iid;
3694 * We might get called multiple times:
3695 * - mono_class_init ()
3696 * - mono_class_setup_vtable ().
3697 * - mono_class_setup_interface_offsets ().
3698 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3699 * means we have to overwrite those when called from other places (#4440).
3701 if (klass->interfaces_packed) {
3703 g_assert (klass->interface_offsets_count == interface_offsets_count);
3707 klass->interface_offsets_count = interface_offsets_count;
3708 klass->interfaces_packed = (MonoClass **)mono_class_alloc (klass, sizeof (MonoClass*) * interface_offsets_count);
3709 klass->interface_offsets_packed = (guint16 *)mono_class_alloc (klass, sizeof (guint16) * interface_offsets_count);
3710 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3711 #ifdef COMPRESSED_INTERFACE_BITMAP
3712 bitmap = g_malloc0 (bsize);
3714 bitmap = (uint8_t *)mono_class_alloc0 (klass, bsize);
3716 for (i = 0; i < interface_offsets_count; i++) {
3717 int id = interfaces_full [i]->interface_id;
3718 bitmap [id >> 3] |= (1 << (id & 7));
3719 klass->interfaces_packed [i] = interfaces_full [i];
3720 klass->interface_offsets_packed [i] = interface_offsets_full [i];
3721 /*if (num_array_interfaces)
3722 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]);*/
3724 #ifdef COMPRESSED_INTERFACE_BITMAP
3725 i = mono_compress_bitmap (NULL, bitmap, bsize);
3726 klass->interface_bitmap = mono_class_alloc0 (klass, i);
3727 mono_compress_bitmap (klass->interface_bitmap, bitmap, bsize);
3730 klass->interface_bitmap = bitmap;
3733 mono_loader_unlock ();
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 setup_interface_offsets (klass, 0, FALSE);
3769 /*Checks if @klass has @parent as one of it's parents type gtd
3773 * Bar<T> : Foo<Bar<Bar<T>>>
3777 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3779 klass = mono_class_get_generic_type_definition (klass);
3780 parent = mono_class_get_generic_type_definition (parent);
3781 mono_class_setup_supertypes (klass);
3782 mono_class_setup_supertypes (parent);
3784 return klass->idepth >= parent->idepth &&
3785 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3789 mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup)
3791 MonoGenericInst *ginst;
3794 if (!mono_class_is_ginst (klass)) {
3795 mono_class_setup_vtable_full (klass, in_setup);
3796 return !mono_class_has_failure (klass);
3799 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup);
3800 if (mono_class_set_type_load_failure_causedby_class (klass, mono_class_get_generic_class (klass)->container_class, "Failed to load generic definition vtable"))
3803 ginst = mono_class_get_generic_class (klass)->context.class_inst;
3804 for (i = 0; i < ginst->type_argc; ++i) {
3806 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3808 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3809 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3810 if (mono_class_has_gtd_parent (klass, arg) || mono_class_has_gtd_parent (arg, klass))
3812 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3813 mono_class_set_type_load_failure (klass, "Failed to load generic parameter %d", i);
3821 * mono_class_setup_vtable:
3823 * Creates the generic vtable of CLASS.
3824 * Initializes the following fields in MonoClass:
3827 * Plus all the fields initialized by setup_interface_offsets ().
3828 * If there is an error during vtable construction, klass->has_failure
3829 * is set and details are stored in a MonoErrorBoxed.
3831 * LOCKING: Acquires the loader lock.
3834 mono_class_setup_vtable (MonoClass *klass)
3836 mono_class_setup_vtable_full (klass, NULL);
3840 mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
3843 MonoMethod **overrides;
3844 MonoGenericContext *context;
3852 if (MONO_CLASS_IS_INTERFACE (klass)) {
3853 /* This sets method->slot for all methods if this is an interface */
3854 mono_class_setup_methods (klass);
3858 if (mono_class_has_failure (klass))
3861 if (g_list_find (in_setup, klass))
3864 mono_loader_lock ();
3866 if (klass->vtable) {
3867 mono_loader_unlock ();
3871 mono_stats.generic_vtable_count ++;
3872 in_setup = g_list_prepend (in_setup, klass);
3874 if (mono_class_is_ginst (klass)) {
3875 if (!mono_class_check_vtable_constraints (klass, in_setup)) {
3876 mono_loader_unlock ();
3877 g_list_remove (in_setup, klass);
3881 context = mono_class_get_context (klass);
3882 type_token = mono_class_get_generic_class (klass)->container_class->type_token;
3884 context = (MonoGenericContext *) mono_class_try_get_generic_container (klass); //FIXME is this a case of a try?
3885 type_token = klass->type_token;
3888 if (image_is_dynamic (klass->image)) {
3889 /* Generic instances can have zero method overrides without causing any harm.
3890 * This is true since we don't do layout all over again for them, we simply inflate
3891 * the layout of the parent.
3893 mono_reflection_get_dynamic_overrides (klass, &overrides, &onum, &error);
3894 if (!is_ok (&error)) {
3895 mono_loader_unlock ();
3896 g_list_remove (in_setup, klass);
3897 mono_class_set_type_load_failure (klass, "Could not load list of method overrides due to %s", mono_error_get_message (&error));
3898 mono_error_cleanup (&error);
3902 /* The following call fails if there are missing methods in the type */
3903 /* FIXME it's probably a good idea to avoid this for generic instances. */
3904 ok = mono_class_get_overrides_full (klass->image, type_token, &overrides, &onum, context);
3908 mono_class_setup_vtable_general (klass, overrides, onum, in_setup);
3910 mono_class_set_type_load_failure (klass, "Could not load list of method overrides");
3914 mono_loader_unlock ();
3915 g_list_remove (in_setup, klass);
3920 #define DEBUG_INTERFACE_VTABLE_CODE 0
3921 #define TRACE_INTERFACE_VTABLE_CODE 0
3922 #define VERIFY_INTERFACE_VTABLE_CODE 0
3923 #define VTABLE_SELECTOR (1)
3925 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3926 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3927 if (!(VTABLE_SELECTOR)) break; \
3931 #define DEBUG_INTERFACE_VTABLE(stmt)
3934 #if TRACE_INTERFACE_VTABLE_CODE
3935 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3936 if (!(VTABLE_SELECTOR)) break; \
3940 #define TRACE_INTERFACE_VTABLE(stmt)
3943 #if VERIFY_INTERFACE_VTABLE_CODE
3944 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3945 if (!(VTABLE_SELECTOR)) break; \
3949 #define VERIFY_INTERFACE_VTABLE(stmt)
3953 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3955 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3959 GString *res = g_string_new ("");
3961 g_string_append_c (res, '(');
3962 for (i = 0; i < sig->param_count; ++i) {
3964 g_string_append_c (res, ',');
3965 mono_type_get_desc (res, sig->params [i], include_namespace);
3967 g_string_append (res, ")=>");
3968 if (sig->ret != NULL) {
3969 mono_type_get_desc (res, sig->ret, include_namespace);
3971 g_string_append (res, "NULL");
3974 g_string_free (res, FALSE);
3978 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3979 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3980 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3981 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3989 is_wcf_hack_disabled (void)
3991 static gboolean disabled;
3992 static gboolean inited = FALSE;
3994 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
4001 check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
4003 MonoMethodSignature *cmsig, *imsig;
4004 if (strcmp (im->name, cm->name) == 0) {
4005 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
4006 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
4009 if (! slot_is_empty) {
4010 if (require_newslot) {
4011 if (! interface_is_explicitly_implemented_by_class) {
4012 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
4015 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4016 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
4020 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
4023 cmsig = mono_method_signature (cm);
4024 imsig = mono_method_signature (im);
4025 if (!cmsig || !imsig) {
4026 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
4030 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4031 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
4032 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4033 TRACE_INTERFACE_VTABLE (printf ("]"));
4036 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
4037 if (mono_security_core_clr_enabled ())
4038 mono_security_core_clr_check_override (klass, cm, im);
4040 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
4041 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4042 char *body_name = mono_method_full_name (cm, TRUE);
4043 char *decl_name = mono_method_full_name (im, TRUE);
4044 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4052 MonoClass *ic = im->klass;
4053 const char *ic_name_space = ic->name_space;
4054 const char *ic_name = ic->name;
4057 if (! require_newslot) {
4058 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
4061 if (cm->klass->rank == 0) {
4062 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
4065 cmsig = mono_method_signature (cm);
4066 imsig = mono_method_signature (im);
4067 if (!cmsig || !imsig) {
4068 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
4072 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4073 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
4074 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4075 TRACE_INTERFACE_VTABLE (printf ("]"));
4078 if (mono_class_get_image (ic) != mono_defaults.corlib) {
4079 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
4082 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
4083 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
4086 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))) {
4087 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
4091 subname = strstr (cm->name, ic_name_space);
4092 if (subname != cm->name) {
4093 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
4096 subname += strlen (ic_name_space);
4097 if (subname [0] != '.') {
4098 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
4102 if (strstr (subname, ic_name) != subname) {
4103 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
4106 subname += strlen (ic_name);
4107 if (subname [0] != '.') {
4108 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
4112 if (strcmp (subname, im->name) != 0) {
4113 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
4117 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
4118 if (mono_security_core_clr_enabled ())
4119 mono_security_core_clr_check_override (klass, cm, im);
4121 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
4122 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4123 char *body_name = mono_method_full_name (cm, TRUE);
4124 char *decl_name = mono_method_full_name (im, TRUE);
4125 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4135 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
4137 foreach_override (gpointer key, gpointer value, gpointer user_data) {
4138 MonoMethod *method = key;
4139 MonoMethod *override = value;
4140 MonoClass *method_class = mono_method_get_class (method);
4141 MonoClass *override_class = mono_method_get_class (override);
4143 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
4144 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
4145 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
4148 print_overrides (GHashTable *override_map, const char *message) {
4150 printf ("Override map \"%s\" START:\n", message);
4151 g_hash_table_foreach (override_map, foreach_override, NULL);
4152 printf ("Override map \"%s\" END.\n", message);
4154 printf ("Override map \"%s\" EMPTY.\n", message);
4158 print_vtable_full (MonoClass *klass, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
4159 char *full_name = mono_type_full_name (&klass->byval_arg);
4163 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
4165 if (print_interfaces) {
4166 print_implemented_interfaces (klass);
4167 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
4170 if (klass->parent) {
4171 parent_size = klass->parent->vtable_size;
4175 for (i = 0; i < size; ++i) {
4176 MonoMethod *cm = vtable [i];
4177 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
4178 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
4180 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
4188 #if VERIFY_INTERFACE_VTABLE_CODE
4190 mono_method_try_get_vtable_index (MonoMethod *method)
4192 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4193 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4194 if (imethod->declaring->is_generic)
4195 return imethod->declaring->slot;
4197 return method->slot;
4201 mono_class_verify_vtable (MonoClass *klass)
4204 char *full_name = mono_type_full_name (&klass->byval_arg);
4206 printf ("*** Verifying VTable of class '%s' \n", full_name);
4210 if (!klass->methods)
4213 for (i = 0; i < klass->method.count; ++i) {
4214 MonoMethod *cm = klass->methods [i];
4217 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4221 full_name = mono_method_full_name (cm, TRUE);
4223 slot = mono_method_try_get_vtable_index (cm);
4225 if (slot >= klass->vtable_size) {
4226 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, klass->vtable_size);
4230 if (slot >= 0 && klass->vtable [slot] != cm && (klass->vtable [slot])) {
4231 char *other_name = klass->vtable [slot] ? mono_method_full_name (klass->vtable [slot], TRUE) : g_strdup ("[null value]");
4232 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4233 g_free (other_name);
4236 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4243 print_unimplemented_interface_method_info (MonoClass *klass, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4245 char *method_signature;
4248 for (index = 0; index < onum; ++index) {
4249 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4250 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4252 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4253 type_name = mono_type_full_name (&klass->byval_arg);
4254 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4255 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4256 g_free (method_signature);
4258 mono_class_setup_methods (klass);
4259 if (mono_class_has_failure (klass)) {
4260 char *name = mono_type_get_full_name (klass);
4261 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4265 for (index = 0; index < klass->method.count; ++index) {
4266 MonoMethod *cm = klass->methods [index];
4267 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4269 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4270 g_free (method_signature);
4275 mono_method_get_method_definition (MonoMethod *method)
4277 while (method->is_inflated)
4278 method = ((MonoMethodInflated*)method)->declaring;
4283 verify_class_overrides (MonoClass *klass, MonoMethod **overrides, int onum)
4287 for (i = 0; i < onum; ++i) {
4288 MonoMethod *decl = overrides [i * 2];
4289 MonoMethod *body = overrides [i * 2 + 1];
4291 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (klass)) {
4292 mono_class_set_type_load_failure (klass, "Method belongs to a different class than the declared one");
4296 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4297 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4298 mono_class_set_type_load_failure (klass, "Method must not be static to override a base type");
4300 mono_class_set_type_load_failure (klass, "Method must be virtual to override a base type");
4304 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4305 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4306 mono_class_set_type_load_failure (klass, "Cannot override a static method in a base type");
4308 mono_class_set_type_load_failure (klass, "Cannot override a non virtual method in a base type");
4312 if (!mono_class_is_assignable_from_slow (decl->klass, klass)) {
4313 mono_class_set_type_load_failure (klass, "Method overrides a class or interface that is not extended or implemented by this type");
4317 body = mono_method_get_method_definition (body);
4318 decl = mono_method_get_method_definition (decl);
4320 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4321 char *body_name = mono_method_full_name (body, TRUE);
4322 char *decl_name = mono_method_full_name (decl, TRUE);
4323 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4333 mono_class_need_stelemref_method (MonoClass *klass)
4335 return klass->rank == 1 && MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg);
4339 * LOCKING: this is supposed to be called with the loader lock held.
4342 mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int onum, GList *in_setup)
4346 MonoMethod **vtable;
4347 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4348 GPtrArray *ifaces = NULL;
4349 GHashTable *override_map = NULL;
4351 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4352 int first_non_interface_slot;
4354 GSList *virt_methods = NULL, *l;
4355 int stelemref_slot = 0;
4360 if (overrides && !verify_class_overrides (klass, overrides, onum))
4363 ifaces = mono_class_get_implemented_interfaces (klass, &error);
4364 if (!mono_error_ok (&error)) {
4365 char *name = mono_type_get_full_name (klass);
4366 mono_class_set_type_load_failure (klass, "Could not resolve %s interfaces due to %s", name, mono_error_get_message (&error));
4368 mono_error_cleanup (&error);
4370 } else if (ifaces) {
4371 for (i = 0; i < ifaces->len; i++) {
4372 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
4373 max_vtsize += ic->method.count;
4375 g_ptr_array_free (ifaces, TRUE);
4379 if (klass->parent) {
4380 mono_class_init (klass->parent);
4381 mono_class_setup_vtable_full (klass->parent, in_setup);
4383 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class failed to load"))
4386 max_vtsize += klass->parent->vtable_size;
4387 cur_slot = klass->parent->vtable_size;
4390 max_vtsize += klass->method.count;
4392 /*Array have a slot for stelemref*/
4393 if (mono_class_need_stelemref_method (klass)) {
4394 stelemref_slot = cur_slot;
4399 vtable = (MonoMethod **)alloca (sizeof (gpointer) * max_vtsize);
4400 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4402 /* printf ("METAINIT %s.%s\n", klass->name_space, klass->name); */
4404 cur_slot = setup_interface_offsets (klass, cur_slot, TRUE);
4405 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4408 max_iid = klass->max_interface_id;
4409 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4411 /* Optimized version for generic instances */
4412 if (mono_class_is_ginst (klass)) {
4414 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4417 mono_class_setup_vtable_full (gklass, in_setup);
4418 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Could not load generic definition"))
4421 tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * gklass->vtable_size);
4422 klass->vtable_size = gklass->vtable_size;
4423 for (i = 0; i < gklass->vtable_size; ++i)
4424 if (gklass->vtable [i]) {
4425 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], klass, mono_class_get_context (klass), &error);
4426 if (!mono_error_ok (&error)) {
4427 mono_class_set_type_load_failure (klass, "Could not inflate method due to %s", mono_error_get_message (&error));
4428 mono_error_cleanup (&error);
4432 tmp [i]->slot = gklass->vtable [i]->slot;
4434 mono_memory_barrier ();
4435 klass->vtable = tmp;
4437 /* Have to set method->slot for abstract virtual methods */
4438 if (klass->methods && gklass->methods) {
4439 for (i = 0; i < klass->method.count; ++i)
4440 if (klass->methods [i]->slot == -1)
4441 klass->methods [i]->slot = gklass->methods [i]->slot;
4447 if (klass->parent && klass->parent->vtable_size) {
4448 MonoClass *parent = klass->parent;
4451 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4453 // Also inherit parent interface vtables, just as a starting point.
4454 // This is needed otherwise bug-77127.exe fails when the property methods
4455 // have different names in the iterface and the class, because for child
4456 // classes the ".override" information is not used anymore.
4457 for (i = 0; i < parent->interface_offsets_count; i++) {
4458 MonoClass *parent_interface = parent->interfaces_packed [i];
4459 int interface_offset = mono_class_interface_offset (klass, parent_interface);
4460 /*FIXME this is now dead code as this condition will never hold true.
4461 Since interface offsets are inherited then the offset of an interface implemented
4462 by a parent will never be the out of it's vtable boundary.
4464 if (interface_offset >= parent->vtable_size) {
4465 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4468 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4469 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4470 for (j = 0; j < parent_interface->method.count && !mono_class_has_failure (klass); j++) {
4471 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4472 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4473 parent_interface_offset + j, parent_interface_offset, j,
4474 interface_offset + j, interface_offset, j));
4481 /*Array have a slot for stelemref*/
4482 if (mono_class_need_stelemref_method (klass)) {
4483 MonoMethod *method = mono_marshal_get_virtual_stelemref (klass);
4485 method->slot = stelemref_slot;
4487 g_assert (method->slot == stelemref_slot);
4489 vtable [stelemref_slot] = method;
4492 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4493 /* override interface methods */
4494 for (i = 0; i < onum; i++) {
4495 MonoMethod *decl = overrides [i*2];
4496 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4498 dslot = mono_method_get_vtable_slot (decl);
4500 mono_class_set_type_load_failure (klass, "");
4504 dslot += mono_class_interface_offset (klass, decl->klass);
4505 vtable [dslot] = overrides [i*2 + 1];
4506 vtable [dslot]->slot = dslot;
4508 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4510 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4512 if (mono_security_core_clr_enabled ())
4513 mono_security_core_clr_check_override (klass, vtable [dslot], decl);
4516 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4517 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4520 * Create a list of virtual methods to avoid calling
4521 * mono_class_get_virtual_methods () which is slow because of the metadata
4525 gpointer iter = NULL;
4528 virt_methods = NULL;
4529 while ((cm = mono_class_get_virtual_methods (klass, &iter))) {
4530 virt_methods = g_slist_prepend (virt_methods, cm);
4532 if (mono_class_has_failure (klass))
4536 // Loop on all implemented interfaces...
4537 for (i = 0; i < klass->interface_offsets_count; i++) {
4538 MonoClass *parent = klass->parent;
4540 gboolean interface_is_explicitly_implemented_by_class;
4543 ic = klass->interfaces_packed [i];
4544 ic_offset = mono_class_interface_offset (klass, ic);
4546 mono_class_setup_methods (ic);
4547 if (mono_class_has_failure (ic))
4550 // Check if this interface is explicitly implemented (instead of just inherited)
4551 if (parent != NULL) {
4552 int implemented_interfaces_index;
4553 interface_is_explicitly_implemented_by_class = FALSE;
4554 for (implemented_interfaces_index = 0; implemented_interfaces_index < klass->interface_count; implemented_interfaces_index++) {
4555 if (ic == klass->interfaces [implemented_interfaces_index]) {
4556 interface_is_explicitly_implemented_by_class = TRUE;
4561 interface_is_explicitly_implemented_by_class = TRUE;
4564 // Loop on all interface methods...
4565 for (im_index = 0; im_index < ic->method.count; im_index++) {
4566 MonoMethod *im = ic->methods [im_index];
4567 int im_slot = ic_offset + im->slot;
4568 MonoMethod *override_im = (override_map != NULL) ? (MonoMethod *)g_hash_table_lookup (override_map, im) : NULL;
4570 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4573 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4575 // If there is an explicit implementation, just use it right away,
4576 // otherwise look for a matching method
4577 if (override_im == NULL) {
4581 // First look for a suitable method among the class methods
4582 for (l = virt_methods; l; l = l->next) {
4583 cm = (MonoMethod *)l->data;
4584 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)));
4585 if (check_interface_method_override (klass, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
4586 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4587 vtable [im_slot] = cm;
4588 /* Why do we need this? */
4593 TRACE_INTERFACE_VTABLE (printf ("\n"));
4594 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4598 // If the slot is still empty, look in all the inherited virtual methods...
4599 if ((vtable [im_slot] == NULL) && klass->parent != NULL) {
4600 MonoClass *parent = klass->parent;
4601 // Reverse order, so that last added methods are preferred
4602 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4603 MonoMethod *cm = parent->vtable [cm_index];
4605 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));
4606 if ((cm != NULL) && check_interface_method_override (klass, im, cm, FALSE, FALSE, TRUE)) {
4607 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4608 vtable [im_slot] = cm;
4609 /* Why do we need this? */
4615 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4617 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4621 g_assert (vtable [im_slot] == override_im);
4626 // If the class is not abstract, check that all its interface slots are full.
4627 // The check is done here and not directly at the end of the loop above because
4628 // it can happen (for injected generic array interfaces) that the same slot is
4629 // processed multiple times (those interfaces have overlapping slots), and it
4630 // will not always be the first pass the one that fills the slot.
4631 if (!mono_class_is_abstract (klass)) {
4632 for (i = 0; i < klass->interface_offsets_count; i++) {
4636 ic = klass->interfaces_packed [i];
4637 ic_offset = mono_class_interface_offset (klass, ic);
4639 for (im_index = 0; im_index < ic->method.count; im_index++) {
4640 MonoMethod *im = ic->methods [im_index];
4641 int im_slot = ic_offset + im->slot;
4643 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4646 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4647 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4648 if (vtable [im_slot] == NULL) {
4649 print_unimplemented_interface_method_info (klass, ic, im, im_slot, overrides, onum);
4656 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4657 for (l = virt_methods; l; l = l->next) {
4658 cm = (MonoMethod *)l->data;
4660 * If the method is REUSE_SLOT, we must check in the
4661 * base class for a method to override.
4663 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4665 for (k = klass->parent; k ; k = k->parent) {
4670 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4671 MonoMethodSignature *cmsig, *m1sig;
4673 cmsig = mono_method_signature (cm);
4674 m1sig = mono_method_signature (m1);
4676 if (!cmsig || !m1sig) {
4677 /* FIXME proper error message */
4678 mono_class_set_type_load_failure (klass, "");
4682 if (!strcmp(cm->name, m1->name) &&
4683 mono_metadata_signature_equal (cmsig, m1sig)) {
4685 if (mono_security_core_clr_enabled ())
4686 mono_security_core_clr_check_override (klass, cm, m1);
4688 slot = mono_method_get_vtable_slot (m1);
4692 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4693 char *body_name = mono_method_full_name (cm, TRUE);
4694 char *decl_name = mono_method_full_name (m1, TRUE);
4695 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4701 g_assert (cm->slot < max_vtsize);
4703 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4704 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4705 mono_method_full_name (m1, 1), m1,
4706 mono_method_full_name (cm, 1), cm));
4707 g_hash_table_insert (override_map, m1, cm);
4711 if (mono_class_has_failure (k))
4721 /*Non final newslot methods must be given a non-interface vtable slot*/
4722 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4726 cm->slot = cur_slot++;
4728 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4729 vtable [cm->slot] = cm;
4732 /* override non interface methods */
4733 for (i = 0; i < onum; i++) {
4734 MonoMethod *decl = overrides [i*2];
4735 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4736 g_assert (decl->slot != -1);
4737 vtable [decl->slot] = overrides [i*2 + 1];
4738 overrides [i * 2 + 1]->slot = decl->slot;
4740 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4741 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4742 mono_method_full_name (decl, 1), decl,
4743 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4744 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4746 if (mono_security_core_clr_enabled ())
4747 mono_security_core_clr_check_override (klass, vtable [decl->slot], decl);
4752 * If a method occupies more than one place in the vtable, and it is
4753 * overriden, then change the other occurances too.
4758 for (i = 0; i < max_vtsize; ++i)
4760 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4762 cm = (MonoMethod *)g_hash_table_lookup (override_map, vtable [i]);
4767 g_hash_table_destroy (override_map);
4768 override_map = NULL;
4771 g_slist_free (virt_methods);
4772 virt_methods = NULL;
4774 /* Ensure that all vtable slots are filled with concrete instance methods */
4775 if (!mono_class_is_abstract (klass)) {
4776 for (i = 0; i < cur_slot; ++i) {
4777 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4778 char *type_name = mono_type_get_full_name (klass);
4779 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4780 mono_class_set_type_load_failure (klass, "Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name);
4782 g_free (method_name);
4788 if (mono_class_is_ginst (klass)) {
4789 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4791 mono_class_init (gklass);
4793 klass->vtable_size = MAX (gklass->vtable_size, cur_slot);
4795 /* Check that the vtable_size value computed in mono_class_init () is correct */
4796 if (klass->vtable_size)
4797 g_assert (cur_slot == klass->vtable_size);
4798 klass->vtable_size = cur_slot;
4801 /* Try to share the vtable with our parent. */
4802 if (klass->parent && (klass->parent->vtable_size == klass->vtable_size) && (memcmp (klass->parent->vtable, vtable, sizeof (gpointer) * klass->vtable_size) == 0)) {
4803 mono_memory_barrier ();
4804 klass->vtable = klass->parent->vtable;
4806 MonoMethod **tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * klass->vtable_size);
4807 memcpy (tmp, vtable, sizeof (gpointer) * klass->vtable_size);
4808 mono_memory_barrier ();
4809 klass->vtable = tmp;
4812 DEBUG_INTERFACE_VTABLE (print_vtable_full (klass, klass->vtable, klass->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4813 if (mono_print_vtable) {
4816 print_implemented_interfaces (klass);
4818 for (i = 0; i <= max_iid; i++)
4819 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
4822 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&klass->byval_arg),
4823 klass->vtable_size, icount);
4825 for (i = 0; i < cur_slot; ++i) {
4830 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4831 mono_method_full_name (cm, TRUE));
4837 printf ("Interfaces %s.%s (max_iid = %d)\n", klass->name_space,
4838 klass->name, max_iid);
4840 for (i = 0; i < klass->interface_count; i++) {
4841 ic = klass->interfaces [i];
4842 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4843 mono_class_interface_offset (klass, ic),
4844 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4847 for (k = klass->parent; k ; k = k->parent) {
4848 for (i = 0; i < k->interface_count; i++) {
4849 ic = k->interfaces [i];
4850 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4851 mono_class_interface_offset (klass, ic),
4852 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4858 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (klass));
4863 char *name = mono_type_get_full_name (klass);
4864 mono_class_set_type_load_failure (klass, "VTable setup of type %s failed", name);
4867 g_hash_table_destroy (override_map);
4869 g_slist_free (virt_methods);
4874 * mono_method_get_vtable_slot:
4876 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4877 * LOCKING: Acquires the loader lock.
4879 * FIXME Use proper MonoError machinery here.
4882 mono_method_get_vtable_slot (MonoMethod *method)
4884 if (method->slot == -1) {
4885 mono_class_setup_vtable (method->klass);
4886 if (mono_class_has_failure (method->klass))
4888 if (method->slot == -1) {
4892 if (!mono_class_is_ginst (method->klass)) {
4893 g_assert (method->is_inflated);
4894 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4897 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4898 g_assert (mono_class_is_ginst (method->klass));
4899 gklass = mono_class_get_generic_class (method->klass)->container_class;
4900 mono_class_setup_methods (method->klass);
4901 g_assert (method->klass->methods);
4902 for (i = 0; i < method->klass->method.count; ++i) {
4903 if (method->klass->methods [i] == method)
4906 g_assert (i < method->klass->method.count);
4907 g_assert (gklass->methods);
4908 method->slot = gklass->methods [i]->slot;
4910 g_assert (method->slot != -1);
4912 return method->slot;
4916 * mono_method_get_vtable_index:
4919 * Returns the index into the runtime vtable to access the method or,
4920 * in the case of a virtual generic method, the virtual generic method
4921 * thunk. Returns -1 on failure.
4923 * FIXME Use proper MonoError machinery here.
4926 mono_method_get_vtable_index (MonoMethod *method)
4928 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4929 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4930 if (imethod->declaring->is_generic)
4931 return mono_method_get_vtable_slot (imethod->declaring);
4933 return mono_method_get_vtable_slot (method);
4936 static MonoMethod *default_ghc = NULL;
4937 static MonoMethod *default_finalize = NULL;
4938 static int finalize_slot = -1;
4939 static int ghc_slot = -1;
4942 initialize_object_slots (MonoClass *klass)
4947 if (klass == mono_defaults.object_class) {
4948 mono_class_setup_vtable (klass);
4949 for (i = 0; i < klass->vtable_size; ++i) {
4950 MonoMethod *cm = klass->vtable [i];
4952 if (!strcmp (cm->name, "GetHashCode"))
4954 else if (!strcmp (cm->name, "Finalize"))
4958 g_assert (ghc_slot > 0);
4959 default_ghc = klass->vtable [ghc_slot];
4961 g_assert (finalize_slot > 0);
4962 default_finalize = klass->vtable [finalize_slot];
4967 MonoMethod *array_method;
4969 } GenericArrayMethodInfo;
4971 static int generic_array_method_num = 0;
4972 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4975 generic_array_methods (MonoClass *klass)
4977 int i, count_generic = 0;
4978 GList *list = NULL, *tmp;
4979 if (generic_array_method_num)
4980 return generic_array_method_num;
4981 mono_class_setup_methods (klass->parent); /*This is setting up System.Array*/
4982 g_assert (!mono_class_has_failure (klass->parent)); /*So hitting this assert is a huge problem*/
4983 for (i = 0; i < klass->parent->method.count; i++) {
4984 MonoMethod *m = klass->parent->methods [i];
4985 if (!strncmp (m->name, "InternalArray__", 15)) {
4987 list = g_list_prepend (list, m);
4990 list = g_list_reverse (list);
4991 generic_array_method_info = (GenericArrayMethodInfo *)mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4993 for (tmp = list; tmp; tmp = tmp->next) {
4994 const char *mname, *iname;
4996 MonoMethod *m = (MonoMethod *)tmp->data;
4997 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4998 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
5000 generic_array_method_info [i].array_method = m;
5001 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
5002 iname = "System.Collections.Generic.ICollection`1.";
5003 mname = m->name + 27;
5004 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
5005 iname = "System.Collections.Generic.IEnumerable`1.";
5006 mname = m->name + 27;
5007 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
5008 iname = "System.Collections.Generic.IReadOnlyList`1.";
5009 mname = m->name + strlen (ireadonlylist_prefix);
5010 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
5011 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
5012 mname = m->name + strlen (ireadonlycollection_prefix);
5013 } else if (!strncmp (m->name, "InternalArray__", 15)) {
5014 iname = "System.Collections.Generic.IList`1.";
5015 mname = m->name + 15;
5017 g_assert_not_reached ();
5020 name = (gchar *)mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
5021 strcpy (name, iname);
5022 strcpy (name + strlen (iname), mname);
5023 generic_array_method_info [i].name = name;
5026 /*g_print ("array generic methods: %d\n", count_generic);*/
5028 generic_array_method_num = count_generic;
5030 return generic_array_method_num;
5034 setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos)
5036 MonoGenericContext tmp_context;
5039 tmp_context.class_inst = NULL;
5040 tmp_context.method_inst = mono_class_get_generic_class (iface)->context.class_inst;
5041 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
5043 for (i = 0; i < generic_array_method_num; i++) {
5045 MonoMethod *m = generic_array_method_info [i].array_method;
5046 MonoMethod *inflated;
5048 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
5049 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
5050 methods [pos++] = mono_marshal_get_generic_array_helper (klass, iface, generic_array_method_info [i].name, inflated);
5055 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
5057 int null_length = strlen ("(null)");
5058 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
5059 char *s = (char *)mono_image_alloc (image, len);
5062 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
5063 g_assert (result == len - 1);
5070 * @klass: the class to initialize
5072 * Compute the instance_size, class_size and other infos that cannot be
5073 * computed at mono_class_get() time. Also compute vtable_size if possible.
5074 * Returns TRUE on success or FALSE if there was a problem in loading
5075 * the type (incorrect assemblies, missing assemblies, methods, etc).
5076 * Initializes the following fields in @klass:
5077 * - all the fields initialized by mono_class_init_sizes ()
5082 * LOCKING: Acquires the loader lock.
5085 mono_class_init (MonoClass *klass)
5087 int i, vtable_size = 0, array_method_count = 0;
5088 MonoCachedClassInfo cached_info;
5089 gboolean has_cached_info;
5090 gboolean locked = FALSE;
5091 gboolean ghcimpl = FALSE;
5092 gboolean has_cctor = FALSE;
5093 int first_iface_slot = 0;
5097 /* Double-checking locking pattern */
5098 if (klass->inited || mono_class_has_failure (klass))
5099 return !mono_class_has_failure (klass);
5101 /*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/
5104 * This function can recursively call itself.
5106 GSList *init_list = (GSList *)mono_native_tls_get_value (init_pending_tls_id);
5107 if (g_slist_find (init_list, klass)) {
5108 mono_class_set_type_load_failure (klass, "Recursive type definition detected");
5111 init_list = g_slist_prepend (init_list, klass);
5112 mono_native_tls_set_value (init_pending_tls_id, init_list);
5115 * We want to avoid doing complicated work inside locks, so we compute all the required
5116 * information and write it to @klass inside a lock.
5119 if (mono_verifier_is_enabled_for_class (klass) && !mono_verifier_verify_class (klass)) {
5120 mono_class_set_type_load_failure (klass, "%s", concat_two_strings_with_zero (klass->image, klass->name, klass->image->assembly_name));
5124 if (klass->byval_arg.type == MONO_TYPE_ARRAY || klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5125 MonoClass *element_class = klass->element_class;
5126 if (!element_class->inited)
5127 mono_class_init (element_class);
5128 if (mono_class_set_type_load_failure_causedby_class (klass, element_class, "Could not load array element class"))
5132 mono_stats.initialized_class_count++;
5134 if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic) {
5135 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5137 mono_class_init (gklass);
5138 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic Type Definition failed to init"))
5141 mono_class_setup_interface_id (klass);
5144 if (klass->parent && !klass->parent->inited)
5145 mono_class_init (klass->parent);
5147 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
5149 /* Compute instance size etc. */
5150 init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
5151 if (mono_class_has_failure (klass))
5154 mono_class_setup_supertypes (klass);
5157 initialize_object_slots (klass);
5160 * Initialize the rest of the data without creating a generic vtable if possible.
5161 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5162 * also avoid computing a generic vtable.
5164 if (has_cached_info) {
5166 vtable_size = cached_info.vtable_size;
5167 ghcimpl = cached_info.ghcimpl;
5168 has_cctor = cached_info.has_cctor;
5169 } else if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5170 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5171 * The first slot if for array with.
5173 static int szarray_vtable_size[2] = { 0 };
5175 int slot = MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg) ? 0 : 1;
5178 if (!szarray_vtable_size [slot]) {
5179 mono_class_setup_vtable (klass);
5180 szarray_vtable_size [slot] = klass->vtable_size;
5181 vtable_size = klass->vtable_size;
5183 vtable_size = szarray_vtable_size[slot];
5185 } else if (mono_class_is_ginst (klass) && !MONO_CLASS_IS_INTERFACE (klass)) {
5186 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5188 /* Generic instance case */
5189 ghcimpl = gklass->ghcimpl;
5190 has_cctor = gklass->has_cctor;
5192 mono_class_setup_vtable (gklass);
5193 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to init"))
5196 vtable_size = gklass->vtable_size;
5200 /* ghcimpl is not currently used
5202 if (klass->parent) {
5203 MonoMethod *cmethod = klass->vtable [ghc_slot];
5204 if (cmethod->is_inflated)
5205 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5206 if (cmethod == default_ghc) {
5212 /* C# doesn't allow interfaces to have cctors */
5213 if (!MONO_CLASS_IS_INTERFACE (klass) || klass->image != mono_defaults.corlib) {
5214 MonoMethod *cmethod = NULL;
5216 if (klass->type_token && !image_is_dynamic(klass->image)) {
5217 cmethod = find_method_in_metadata (klass, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5218 /* The find_method function ignores the 'flags' argument */
5219 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5222 mono_class_setup_methods (klass);
5223 if (mono_class_has_failure (klass))
5226 for (i = 0; i < klass->method.count; ++i) {
5227 MonoMethod *method = klass->methods [i];
5228 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5229 (strcmp (".cctor", method->name) == 0)) {
5239 array_method_count = 3 + (klass->rank > 1? 2: 1);
5241 if (klass->interface_count) {
5242 int count_generic = generic_array_methods (klass);
5243 array_method_count += klass->interface_count * count_generic;
5247 if (klass->parent) {
5248 if (!klass->parent->vtable_size)
5249 mono_class_setup_vtable (klass->parent);
5250 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class vtable failed to initialize"))
5252 g_assert (klass->parent->vtable_size);
5253 first_iface_slot = klass->parent->vtable_size;
5254 if (mono_class_need_stelemref_method (klass))
5259 * Do the actual changes to @klass inside the loader lock
5261 mono_loader_lock ();
5264 if (klass->inited || mono_class_has_failure (klass)) {
5265 mono_loader_unlock ();
5266 /* Somebody might have gotten in before us */
5267 return !mono_class_has_failure (klass);
5270 mono_stats.initialized_class_count++;
5272 if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic) {
5273 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5275 mono_stats.generic_class_count++;
5277 klass->method = gklass->method;
5278 klass->field = gklass->field;
5281 if (mono_class_is_ginst (klass) || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
5282 klass->nested_classes_inited = TRUE;
5283 klass->ghcimpl = ghcimpl;
5284 klass->has_cctor = has_cctor;
5286 klass->vtable_size = vtable_size;
5287 if (has_cached_info) {
5288 klass->has_finalize = cached_info.has_finalize;
5289 klass->has_finalize_inited = TRUE;
5292 klass->method.count = array_method_count;
5294 mono_loader_unlock ();
5297 setup_interface_offsets (klass, first_iface_slot, TRUE);
5299 if (mono_security_core_clr_enabled ())
5300 mono_security_core_clr_check_inheritance (klass);
5302 if (mono_class_is_ginst (klass) && !mono_verifier_class_is_valid_generic_instantiation (klass))
5303 mono_class_set_type_load_failure (klass, "Invalid generic instantiation");
5308 init_list = g_slist_remove (init_list, klass);
5309 mono_native_tls_set_value (init_pending_tls_id, init_list);
5311 /* Because of the double-checking locking pattern */
5312 mono_memory_barrier ();
5316 mono_loader_unlock ();
5318 return !mono_class_has_failure (klass);
5322 * mono_class_has_finalizer:
5324 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5328 mono_class_has_finalizer (MonoClass *klass)
5330 gboolean has_finalize = FALSE;
5332 if (klass->has_finalize_inited)
5333 return klass->has_finalize;
5335 /* Interfaces and valuetypes are not supposed to have finalizers */
5336 if (!(MONO_CLASS_IS_INTERFACE (klass) || klass->valuetype)) {
5337 MonoMethod *cmethod = NULL;
5339 if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5340 } else if (mono_class_is_ginst (klass)) {
5341 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5343 has_finalize = mono_class_has_finalizer (gklass);
5344 } else if (klass->parent && klass->parent->has_finalize) {
5345 has_finalize = TRUE;
5347 if (klass->parent) {
5349 * Can't search in metadata for a method named Finalize, because that
5350 * ignores overrides.
5352 mono_class_setup_vtable (klass);
5353 if (mono_class_has_failure (klass))
5356 cmethod = klass->vtable [finalize_slot];
5360 g_assert (klass->vtable_size > finalize_slot);
5362 if (klass->parent) {
5363 if (cmethod->is_inflated)
5364 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5365 if (cmethod != default_finalize)
5366 has_finalize = TRUE;
5372 mono_image_lock (klass->image);
5374 if (!klass->has_finalize_inited) {
5375 klass->has_finalize = has_finalize ? 1 : 0;
5377 mono_memory_barrier ();
5378 klass->has_finalize_inited = TRUE;
5381 mono_image_unlock (klass->image);
5383 return klass->has_finalize;
5387 mono_is_corlib_image (MonoImage *image)
5389 return image == mono_defaults.corlib;
5393 * LOCKING: this assumes the loader lock is held
5396 mono_class_setup_mono_type (MonoClass *klass)
5398 const char *name = klass->name;
5399 const char *nspace = klass->name_space;
5400 gboolean is_corlib = mono_is_corlib_image (klass->image);
5402 klass->this_arg.byref = 1;
5403 klass->this_arg.data.klass = klass;
5404 klass->this_arg.type = MONO_TYPE_CLASS;
5405 klass->byval_arg.data.klass = klass;
5406 klass->byval_arg.type = MONO_TYPE_CLASS;
5408 if (is_corlib && !strcmp (nspace, "System")) {
5409 if (!strcmp (name, "ValueType")) {
5411 * do not set the valuetype bit for System.ValueType.
5412 * klass->valuetype = 1;
5414 klass->blittable = TRUE;
5415 } else if (!strcmp (name, "Enum")) {
5417 * do not set the valuetype bit for System.Enum.
5418 * klass->valuetype = 1;
5420 klass->valuetype = 0;
5421 klass->enumtype = 0;
5422 } else if (!strcmp (name, "Object")) {
5423 klass->byval_arg.type = MONO_TYPE_OBJECT;
5424 klass->this_arg.type = MONO_TYPE_OBJECT;
5425 } else if (!strcmp (name, "String")) {
5426 klass->byval_arg.type = MONO_TYPE_STRING;
5427 klass->this_arg.type = MONO_TYPE_STRING;
5428 } else if (!strcmp (name, "TypedReference")) {
5429 klass->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5430 klass->this_arg.type = MONO_TYPE_TYPEDBYREF;
5434 if (klass->valuetype) {
5435 int t = MONO_TYPE_VALUETYPE;
5437 if (is_corlib && !strcmp (nspace, "System")) {
5440 if (!strcmp (name, "Boolean")) {
5441 t = MONO_TYPE_BOOLEAN;
5442 } else if (!strcmp(name, "Byte")) {
5444 klass->blittable = TRUE;
5448 if (!strcmp (name, "Char")) {
5453 if (!strcmp (name, "Double")) {
5455 klass->blittable = TRUE;
5459 if (!strcmp (name, "Int32")) {
5461 klass->blittable = TRUE;
5462 } else if (!strcmp(name, "Int16")) {
5464 klass->blittable = TRUE;
5465 } else if (!strcmp(name, "Int64")) {
5467 klass->blittable = TRUE;
5468 } else if (!strcmp(name, "IntPtr")) {
5470 klass->blittable = TRUE;
5474 if (!strcmp (name, "Single")) {
5476 klass->blittable = TRUE;
5477 } else if (!strcmp(name, "SByte")) {
5479 klass->blittable = TRUE;
5483 if (!strcmp (name, "UInt32")) {
5485 klass->blittable = TRUE;
5486 } else if (!strcmp(name, "UInt16")) {
5488 klass->blittable = TRUE;
5489 } else if (!strcmp(name, "UInt64")) {
5491 klass->blittable = TRUE;
5492 } else if (!strcmp(name, "UIntPtr")) {
5494 klass->blittable = TRUE;
5498 if (!strcmp (name, "TypedReference")) {
5499 t = MONO_TYPE_TYPEDBYREF;
5500 klass->blittable = TRUE;
5504 if (!strcmp (name, "Void")) {
5512 klass->byval_arg.type = (MonoTypeEnum)t;
5513 klass->this_arg.type = (MonoTypeEnum)t;
5516 if (MONO_CLASS_IS_INTERFACE (klass))
5517 klass->interface_id = mono_get_unique_iid (klass);
5522 * COM initialization is delayed until needed.
5523 * However when a [ComImport] attribute is present on a type it will trigger
5524 * the initialization. This is not a problem unless the BCL being executed
5525 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5528 init_com_from_comimport (MonoClass *klass)
5530 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5531 if (mono_security_core_clr_enabled ()) {
5532 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5533 if (!mono_security_core_clr_determine_platform_image (klass->image)) {
5534 /* but it can not be made available for application (i.e. user code) since all COM calls
5535 * are considered native calls. In this case we fail with a TypeLoadException (just like
5536 * Silverlight 2 does */
5537 mono_class_set_type_load_failure (klass, "");
5542 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5544 #endif /*DISABLE_COM*/
5547 * LOCKING: this assumes the loader lock is held
5550 mono_class_setup_parent (MonoClass *klass, MonoClass *parent)
5552 gboolean system_namespace;
5553 gboolean is_corlib = mono_is_corlib_image (klass->image);
5555 system_namespace = !strcmp (klass->name_space, "System") && is_corlib;
5557 /* if root of the hierarchy */
5558 if (system_namespace && !strcmp (klass->name, "Object")) {
5559 klass->parent = NULL;
5560 klass->instance_size = sizeof (MonoObject);
5563 if (!strcmp (klass->name, "<Module>")) {
5564 klass->parent = NULL;
5565 klass->instance_size = 0;
5569 if (!MONO_CLASS_IS_INTERFACE (klass)) {
5570 /* Imported COM Objects always derive from __ComObject. */
5572 if (MONO_CLASS_IS_IMPORT (klass)) {
5573 init_com_from_comimport (klass);
5574 if (parent == mono_defaults.object_class)
5575 parent = mono_class_get_com_object_class ();
5579 /* set the parent to something useful and safe, but mark the type as broken */
5580 parent = mono_defaults.object_class;
5581 mono_class_set_type_load_failure (klass, "");
5585 klass->parent = parent;
5587 if (mono_class_is_ginst (parent) && !parent->name) {
5589 * If the parent is a generic instance, we may get
5590 * called before it is fully initialized, especially
5591 * before it has its name.
5596 #ifndef DISABLE_REMOTING
5597 klass->marshalbyref = parent->marshalbyref;
5598 klass->contextbound = parent->contextbound;
5601 klass->delegate = parent->delegate;
5603 if (MONO_CLASS_IS_IMPORT (klass) || mono_class_is_com_object (parent))
5604 mono_class_set_is_com_object (klass);
5606 if (system_namespace) {
5607 #ifndef DISABLE_REMOTING
5608 if (klass->name [0] == 'M' && !strcmp (klass->name, "MarshalByRefObject"))
5609 klass->marshalbyref = 1;
5611 if (klass->name [0] == 'C' && !strcmp (klass->name, "ContextBoundObject"))
5612 klass->contextbound = 1;
5614 if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate"))
5615 klass->delegate = 1;
5618 if (klass->parent->enumtype || (mono_is_corlib_image (klass->parent->image) && (strcmp (klass->parent->name, "ValueType") == 0) &&
5619 (strcmp (klass->parent->name_space, "System") == 0)))
5620 klass->valuetype = 1;
5621 if (mono_is_corlib_image (klass->parent->image) && ((strcmp (klass->parent->name, "Enum") == 0) && (strcmp (klass->parent->name_space, "System") == 0))) {
5622 klass->valuetype = klass->enumtype = 1;
5624 /*klass->enumtype = klass->parent->enumtype; */
5626 /* initialize com types if COM interfaces are present */
5628 if (MONO_CLASS_IS_IMPORT (klass))
5629 init_com_from_comimport (klass);
5631 klass->parent = NULL;
5637 * mono_class_setup_supertypes:
5640 * Build the data structure needed to make fast type checks work.
5641 * This currently sets two fields in @class:
5642 * - idepth: distance between @class and System.Object in the type
5644 * - supertypes: array of classes: each element has a class in the hierarchy
5645 * starting from @class up to System.Object
5647 * LOCKING: This function is atomic, in case of contention we waste memory.
5650 mono_class_setup_supertypes (MonoClass *klass)
5653 MonoClass **supertypes;
5655 mono_atomic_load_acquire (supertypes, MonoClass **, &klass->supertypes);
5659 if (klass->parent && !klass->parent->supertypes)
5660 mono_class_setup_supertypes (klass->parent);
5662 klass->idepth = klass->parent->idepth + 1;
5666 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, klass->idepth);
5667 supertypes = (MonoClass **)mono_class_alloc0 (klass, sizeof (MonoClass *) * ms);
5669 if (klass->parent) {
5670 CHECKED_METADATA_WRITE_PTR ( supertypes [klass->idepth - 1] , klass );
5673 for (supertype_idx = 0; supertype_idx < klass->parent->idepth; supertype_idx++)
5674 CHECKED_METADATA_WRITE_PTR ( supertypes [supertype_idx] , klass->parent->supertypes [supertype_idx] );
5676 CHECKED_METADATA_WRITE_PTR ( supertypes [0] , klass );
5679 CHECKED_METADATA_WRITE_PTR_ATOMIC ( klass->supertypes , supertypes );
5683 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5685 MonoClass *gtd = (MonoClass*)user_data;
5686 /* Only try to fix generic instances of @gtd */
5687 if (mono_class_get_generic_class (gclass)->container_class != gtd)
5690 /* Check if the generic instance has no parent. */
5691 if (gtd->parent && !gclass->parent)
5692 mono_generic_class_setup_parent (gclass, gtd);
5698 mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char *msg)
5700 mono_class_set_type_load_failure (klass, "%s", msg);
5701 mono_error_set_type_load_class (error, klass, "%s", msg);
5705 * mono_class_create_from_typedef:
5706 * @image: image where the token is valid
5707 * @type_token: typedef token
5708 * @error: used to return any error found while creating the type
5710 * Create the MonoClass* representing the specified type token.
5711 * @type_token must be a TypeDef token.
5713 * FIXME: don't return NULL on failure, just the the caller figure it out.
5716 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5718 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5719 MonoClass *klass, *parent = NULL;
5720 guint32 cols [MONO_TYPEDEF_SIZE];
5721 guint32 cols_next [MONO_TYPEDEF_SIZE];
5722 guint tidx = mono_metadata_token_index (type_token);
5723 MonoGenericContext *context = NULL;
5724 const char *name, *nspace;
5726 MonoClass **interfaces;
5727 guint32 field_last, method_last;
5728 guint32 nesting_tokeen;
5730 mono_error_init (error);
5732 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5733 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5737 mono_loader_lock ();
5739 if ((klass = (MonoClass *)mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5740 mono_loader_unlock ();
5744 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5746 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5747 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5749 if (mono_metadata_has_generic_params (image, type_token)) {
5750 klass = mono_image_alloc0 (image, sizeof (MonoClassGtd));
5751 klass->class_kind = MONO_CLASS_GTD;
5752 classes_size += sizeof (MonoClassGtd);
5755 klass = mono_image_alloc0 (image, sizeof (MonoClassDef));
5756 klass->class_kind = MONO_CLASS_DEF;
5757 classes_size += sizeof (MonoClassDef);
5762 klass->name_space = nspace;
5764 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5766 klass->image = image;
5767 klass->type_token = type_token;
5768 mono_class_set_flags (klass, cols [MONO_TYPEDEF_FLAGS]);
5770 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
5773 * Check whether we're a generic type definition.
5775 if (mono_class_is_gtd (klass)) {
5776 MonoGenericContainer *generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
5777 generic_container->owner.klass = klass;
5778 generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
5779 context = &generic_container->context;
5780 mono_class_set_generic_container (klass, generic_container);
5781 enable_gclass_recording ();
5784 if (cols [MONO_TYPEDEF_EXTENDS]) {
5786 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5788 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5789 /*WARNING: this must satisfy mono_metadata_type_hash*/
5790 klass->this_arg.byref = 1;
5791 klass->this_arg.data.klass = klass;
5792 klass->this_arg.type = MONO_TYPE_CLASS;
5793 klass->byval_arg.data.klass = klass;
5794 klass->byval_arg.type = MONO_TYPE_CLASS;
5796 parent = mono_class_get_checked (image, parent_token, error);
5797 if (parent && context) /* Always inflate */
5798 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5800 if (parent == NULL) {
5801 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5802 goto parent_failure;
5805 for (tmp = parent; tmp; tmp = tmp->parent) {
5807 mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
5808 goto parent_failure;
5810 if (mono_class_is_gtd (klass) && mono_class_is_ginst (tmp) && mono_class_get_generic_class (tmp)->container_class == klass) {
5811 mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
5812 goto parent_failure;
5817 mono_class_setup_parent (klass, parent);
5819 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5820 mono_class_setup_mono_type (klass);
5822 if (mono_class_is_gtd (klass))
5823 disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
5826 * This might access klass->byval_arg for recursion generated by generic constraints,
5827 * so it has to come after setup_mono_type ().
5829 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5830 klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5831 if (!mono_error_ok (error)) {
5832 /*FIXME implement a mono_class_set_failure_from_mono_error */
5833 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5834 mono_loader_unlock ();
5835 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5840 if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5844 if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5848 klass->cast_class = klass->element_class = klass;
5850 if (!klass->enumtype) {
5851 if (!mono_metadata_interfaces_from_typedef_full (
5852 image, type_token, &interfaces, &icount, FALSE, context, error)){
5854 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5855 mono_loader_unlock ();
5856 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5860 klass->interfaces = interfaces;
5861 klass->interface_count = icount;
5862 klass->interfaces_inited = 1;
5865 /*g_print ("Load class %s\n", name);*/
5868 * Compute the field and method lists
5870 klass->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5871 klass->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5873 if (tt->rows > tidx){
5874 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5875 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5876 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5878 field_last = image->tables [MONO_TABLE_FIELD].rows;
5879 method_last = image->tables [MONO_TABLE_METHOD].rows;
5882 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5883 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5884 klass->field.count = field_last - klass->field.first;
5886 klass->field.count = 0;
5888 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5889 klass->method.count = method_last - klass->method.first;
5891 klass->method.count = 0;
5893 /* reserve space to store vector pointer in arrays */
5894 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5895 klass->instance_size += 2 * sizeof (gpointer);
5896 g_assert (klass->field.count == 0);
5899 if (klass->enumtype) {
5900 MonoType *enum_basetype = mono_class_find_enum_basetype (klass, error);
5901 if (!enum_basetype) {
5902 /*set it to a default value as the whole runtime can't handle this to be null*/
5903 klass->cast_class = klass->element_class = mono_defaults.int32_class;
5904 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5905 mono_loader_unlock ();
5906 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5909 klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
5913 * If we're a generic type definition, load the constraints.
5914 * We must do this after the class has been constructed to make certain recursive scenarios
5917 if (mono_class_is_gtd (klass) && !mono_metadata_load_generic_param_constraints_checked (image, type_token, mono_class_get_generic_container (klass), error)) {
5918 mono_class_set_type_load_failure (klass, "Could not load generic parameter constrains due to %s", mono_error_get_message (error));
5919 mono_loader_unlock ();
5920 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5924 if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5925 if (!strncmp (name, "Vector", 6))
5926 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");
5929 mono_loader_unlock ();
5931 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5936 mono_class_setup_mono_type (klass);
5937 mono_loader_unlock ();
5938 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5942 /** Is klass a Nullable<T> ginst? */
5944 mono_class_is_nullable (MonoClass *klass)
5946 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
5947 return gklass && gklass->container_class == mono_defaults.generic_nullable_class;
5951 /** if klass is T? return T */
5953 mono_class_get_nullable_param (MonoClass *klass)
5955 g_assert (mono_class_is_nullable (klass));
5956 return mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
5960 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5964 MonoGenericClass *gclass = mono_class_get_generic_class (klass);
5966 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5967 if (!mono_error_ok (&error)) {
5968 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5969 klass->parent = mono_defaults.object_class;
5970 mono_class_set_type_load_failure (klass, "Parent is a generic type instantiation that failed due to: %s", mono_error_get_message (&error));
5971 mono_error_cleanup (&error);
5975 mono_class_setup_parent (klass, klass->parent);
5977 if (klass->enumtype) {
5978 klass->cast_class = gtd->cast_class;
5979 klass->element_class = gtd->element_class;
5985 * Create the `MonoClass' for an instantiation of a generic type.
5986 * We only do this if we actually need it.
5989 mono_generic_class_get_class (MonoGenericClass *gclass)
5991 MonoClass *klass, *gklass;
5993 if (gclass->cached_class)
5994 return gclass->cached_class;
5996 mono_loader_lock ();
5997 if (gclass->cached_class) {
5998 mono_loader_unlock ();
5999 return gclass->cached_class;
6002 klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClassGenericInst));
6004 gklass = gclass->container_class;
6006 if (record_gclass_instantiation > 0)
6007 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
6009 if (gklass->nested_in) {
6010 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
6011 klass->nested_in = gklass->nested_in;
6014 klass->name = gklass->name;
6015 klass->name_space = gklass->name_space;
6017 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6019 klass->image = gklass->image;
6020 klass->type_token = gklass->type_token;
6021 klass->field.count = gklass->field.count;
6023 klass->class_kind = MONO_CLASS_GINST;
6025 ((MonoClassGenericInst*)klass)->generic_class = gclass;
6027 klass->byval_arg.type = MONO_TYPE_GENERICINST;
6028 klass->this_arg.type = klass->byval_arg.type;
6029 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
6030 klass->this_arg.byref = TRUE;
6031 klass->enumtype = gklass->enumtype;
6032 klass->valuetype = gklass->valuetype;
6034 klass->cast_class = klass->element_class = klass;
6036 if (mono_class_is_nullable (klass))
6037 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
6040 * We're not interested in the nested classes of a generic instance.
6041 * We use the generic type definition to look for nested classes.
6044 mono_generic_class_setup_parent (klass, gklass);
6046 if (gclass->is_dynamic) {
6048 * 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.
6049 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
6050 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
6052 if (!gklass->wastypebuilder)
6055 mono_class_setup_supertypes (klass);
6057 if (klass->enumtype) {
6059 * For enums, gklass->fields might not been set, but instance_size etc. is
6060 * already set in mono_reflection_create_internal_class (). For non-enums,
6061 * these will be computed normally in mono_class_layout_fields ().
6063 klass->instance_size = gklass->instance_size;
6064 klass->sizes.class_size = gklass->sizes.class_size;
6065 mono_memory_barrier ();
6066 klass->size_inited = 1;
6070 mono_memory_barrier ();
6071 gclass->cached_class = klass;
6073 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6075 ++class_ginst_count;
6076 inflated_classes_size += sizeof (MonoClassGenericInst);
6078 mono_loader_unlock ();
6084 get_image_for_container (MonoGenericContainer *container)
6087 if (container->is_anonymous) {
6088 result = container->owner.image;
6091 if (container->is_method) {
6092 MonoMethod *method = container->owner.method;
6093 g_assert_checked (method);
6094 klass = method->klass;
6096 klass = container->owner.klass;
6098 g_assert_checked (klass);
6099 result = klass->image;
6106 get_image_for_generic_param (MonoGenericParam *param)
6108 MonoGenericContainer *container = mono_generic_param_owner (param);
6109 g_assert_checked (container);
6110 return get_image_for_container (container);
6113 // Make a string in the designated image consisting of a single integer.
6114 #define INT_STRING_SIZE 16
6116 make_generic_name_string (MonoImage *image, int num)
6118 char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
6119 g_snprintf (name, INT_STRING_SIZE, "%d", num);
6123 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
6124 // pinfo is derived from param by the caller for us.
6126 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
6128 MonoClass *klass, **ptr;
6130 MonoGenericContainer *container = mono_generic_param_owner (param);
6131 g_assert_checked (container);
6133 MonoImage *image = get_image_for_container (container);
6134 gboolean is_mvar = container->is_method;
6135 gboolean is_anonymous = container->is_anonymous;
6137 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassGenericParam));
6138 klass->class_kind = MONO_CLASS_GPARAM;
6139 classes_size += sizeof (MonoClassGenericParam);
6140 ++class_gparam_count;
6143 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
6145 int n = mono_generic_param_num (param);
6146 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
6150 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , "" );
6151 } else if (is_mvar) {
6152 MonoMethod *omethod = container->owner.method;
6153 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
6155 MonoClass *oklass = container->owner.klass;
6156 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
6159 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6161 // Count non-NULL items in pinfo->constraints
6164 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6168 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6169 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
6171 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
6172 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
6174 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
6177 if (count - pos > 0) {
6178 klass->interface_count = count - pos;
6179 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
6180 klass->interfaces_inited = TRUE;
6181 for (i = pos; i < count; i++)
6182 CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
6185 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
6187 klass->inited = TRUE;
6188 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class , klass );
6189 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
6191 klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6192 klass->this_arg.type = klass->byval_arg.type;
6193 CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param , param );
6194 CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
6195 klass->this_arg.byref = TRUE;
6197 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6198 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6200 /*Init these fields to sane values*/
6201 klass->min_align = 1;
6203 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6204 * constrained to, the JIT depends on this.
6206 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6207 mono_memory_barrier ();
6208 klass->size_inited = 1;
6210 mono_class_setup_supertypes (klass);
6212 if (count - pos > 0) {
6213 mono_class_setup_vtable (klass->parent);
6214 if (mono_class_has_failure (klass->parent))
6215 mono_class_set_type_load_failure (klass, "Failed to setup parent interfaces");
6217 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6223 #define FAST_CACHE_SIZE 16
6226 * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6227 * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6228 * we cache the MonoClasses.
6229 * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6230 * LOCKING: Takes the image lock depending on @take_lock.
6233 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6235 int n = mono_generic_param_num (param);
6236 MonoImage *image = get_image_for_generic_param (param);
6237 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6238 MonoClass *klass = NULL;
6243 // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6244 // For high numbers or constraints we have to use pointer hashes.
6245 if (param->gshared_constraint) {
6246 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6249 mono_image_lock (image);
6250 klass = (MonoClass *)g_hash_table_lookup (ht, param);
6252 mono_image_unlock (image);
6257 if (n < FAST_CACHE_SIZE) {
6259 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6261 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6263 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6266 mono_image_lock (image);
6267 klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6269 mono_image_unlock (image);
6276 * LOCKING: Image lock (param->image) must be held
6279 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6281 int n = mono_generic_param_num (param);
6282 MonoImage *image = get_image_for_generic_param (param);
6283 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6287 if (param->gshared_constraint) {
6288 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6290 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6291 mono_memory_barrier ();
6293 image->mvar_cache_constrained = ht;
6295 image->var_cache_constrained = ht;
6297 g_hash_table_insert (ht, param, klass);
6298 } else if (n < FAST_CACHE_SIZE) {
6300 /* Requires locking to avoid droping an already published class */
6301 if (!image->mvar_cache_fast)
6302 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6303 image->mvar_cache_fast [n] = klass;
6305 if (!image->var_cache_fast)
6306 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6307 image->var_cache_fast [n] = klass;
6310 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6312 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6314 ht = g_hash_table_new (NULL, NULL);
6315 mono_memory_barrier ();
6317 image->mvar_cache_slow = ht;
6319 image->var_cache_slow = ht;
6322 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6327 * LOCKING: Acquires the image lock (@image).
6330 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6332 MonoImage *image = get_image_for_generic_param (param);
6333 MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6334 MonoClass *klass, *klass2;
6336 // If a klass already exists for this object and is cached, return it.
6337 if (pinfo) // Non-anonymous
6338 klass = pinfo->pklass;
6340 klass = get_anon_gparam_class (param, TRUE);
6345 // Create a new klass
6346 klass = make_generic_param_class (param, pinfo);
6348 // Now we need to cache the klass we created.
6349 // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6350 // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6351 // and allow our newly-created klass object to just leak.
6352 mono_memory_barrier ();
6354 mono_image_lock (image);
6356 // Here "klass2" refers to the klass potentially created by the other thread.
6357 if (pinfo) // Repeat check from above
6358 klass2 = pinfo->pklass;
6360 klass2 = get_anon_gparam_class (param, FALSE);
6367 pinfo->pklass = klass;
6369 set_anon_gparam_class (param, klass);
6371 mono_image_unlock (image);
6373 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6375 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED); // Alert profiler about botched class create
6377 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6383 * mono_class_from_generic_parameter:
6384 * @param: Parameter to find/construct a class for.
6385 * @arg2: Is ignored.
6386 * @arg3: Is ignored.
6389 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6391 return mono_class_from_generic_parameter_internal (param);
6396 mono_ptr_class_get (MonoType *type)
6399 MonoClass *el_class;
6403 el_class = mono_class_from_mono_type (type);
6404 image = el_class->image;
6406 mono_image_lock (image);
6407 if (image->ptr_cache) {
6408 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6409 mono_image_unlock (image);
6413 mono_image_unlock (image);
6415 result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassPointer));
6417 classes_size += sizeof (MonoClassPointer);
6418 ++class_pointer_count;
6420 result->parent = NULL; /* no parent for PTR types */
6421 result->name_space = el_class->name_space;
6422 name = g_strdup_printf ("%s*", el_class->name);
6423 result->name = mono_image_strdup (image, name);
6424 result->class_kind = MONO_CLASS_POINTER;
6427 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6429 result->image = el_class->image;
6430 result->inited = TRUE;
6431 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6432 result->cast_class = result->element_class = el_class;
6433 result->blittable = TRUE;
6435 result->byval_arg.type = MONO_TYPE_PTR;
6436 result->this_arg.type = result->byval_arg.type;
6437 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6438 result->this_arg.byref = TRUE;
6440 mono_class_setup_supertypes (result);
6442 mono_image_lock (image);
6443 if (image->ptr_cache) {
6445 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6446 mono_image_unlock (image);
6447 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6451 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6453 g_hash_table_insert (image->ptr_cache, el_class, result);
6454 mono_image_unlock (image);
6456 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6462 mono_fnptr_class_get (MonoMethodSignature *sig)
6465 static GHashTable *ptr_hash = NULL;
6467 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6469 mono_loader_lock ();
6472 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6474 if ((result = (MonoClass *)g_hash_table_lookup (ptr_hash, sig))) {
6475 mono_loader_unlock ();
6478 result = g_new0 (MonoClass, 1);
6480 classes_size += sizeof (MonoClassPointer);
6481 ++class_pointer_count;
6483 result->parent = NULL; /* no parent for PTR types */
6484 result->name_space = "System";
6485 result->name = "MonoFNPtrFakeClass";
6486 result->class_kind = MONO_CLASS_POINTER;
6488 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6490 result->image = mono_defaults.corlib; /* need to fix... */
6491 result->inited = TRUE;
6492 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6493 result->cast_class = result->element_class = result;
6494 result->blittable = TRUE;
6496 result->byval_arg.type = MONO_TYPE_FNPTR;
6497 result->this_arg.type = result->byval_arg.type;
6498 result->this_arg.data.method = result->byval_arg.data.method = sig;
6499 result->this_arg.byref = TRUE;
6500 result->blittable = TRUE;
6502 mono_class_setup_supertypes (result);
6504 g_hash_table_insert (ptr_hash, sig, result);
6506 mono_loader_unlock ();
6508 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6514 * mono_class_from_mono_type:
6515 * @type: describes the type to return
6517 * This returns a MonoClass for the specified MonoType, the value is never NULL.
6520 mono_class_from_mono_type (MonoType *type)
6522 switch (type->type) {
6523 case MONO_TYPE_OBJECT:
6524 return type->data.klass? type->data.klass: mono_defaults.object_class;
6525 case MONO_TYPE_VOID:
6526 return type->data.klass? type->data.klass: mono_defaults.void_class;
6527 case MONO_TYPE_BOOLEAN:
6528 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6529 case MONO_TYPE_CHAR:
6530 return type->data.klass? type->data.klass: mono_defaults.char_class;
6532 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6534 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6536 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6538 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6540 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6542 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6544 return type->data.klass? type->data.klass: mono_defaults.int_class;
6546 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6548 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6550 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6552 return type->data.klass? type->data.klass: mono_defaults.single_class;
6554 return type->data.klass? type->data.klass: mono_defaults.double_class;
6555 case MONO_TYPE_STRING:
6556 return type->data.klass? type->data.klass: mono_defaults.string_class;
6557 case MONO_TYPE_TYPEDBYREF:
6558 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6559 case MONO_TYPE_ARRAY:
6560 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6562 return mono_ptr_class_get (type->data.type);
6563 case MONO_TYPE_FNPTR:
6564 return mono_fnptr_class_get (type->data.method);
6565 case MONO_TYPE_SZARRAY:
6566 return mono_array_class_get (type->data.klass, 1);
6567 case MONO_TYPE_CLASS:
6568 case MONO_TYPE_VALUETYPE:
6569 return type->data.klass;
6570 case MONO_TYPE_GENERICINST:
6571 return mono_generic_class_get_class (type->data.generic_class);
6572 case MONO_TYPE_MVAR:
6574 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6576 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6577 g_assert_not_reached ();
6580 // Yes, this returns NULL, even if it is documented as not doing so, but there
6581 // is no way for the code to make it this far, due to the assert above.
6586 * mono_type_retrieve_from_typespec
6587 * @image: context where the image is created
6588 * @type_spec: typespec token
6589 * @context: the generic context used to evaluate generic instantiations in
6592 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6594 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6596 *did_inflate = FALSE;
6601 if (context && (context->class_inst || context->method_inst)) {
6602 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6604 if (!mono_error_ok (error)) {
6610 *did_inflate = TRUE;
6617 * mono_class_create_from_typespec
6618 * @image: context where the image is created
6619 * @type_spec: typespec token
6620 * @context: the generic context used to evaluate generic instantiations in
6623 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6626 gboolean inflated = FALSE;
6627 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6628 return_val_if_nok (error, NULL);
6629 ret = mono_class_from_mono_type (t);
6631 mono_metadata_free_type (t);
6636 * mono_bounded_array_class_get:
6637 * @element_class: element class
6638 * @rank: the dimension of the array class
6639 * @bounded: whenever the array has non-zero bounds
6641 * Returns: A class object describing the array with element type @element_type and
6645 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6649 MonoClass *parent = NULL;
6650 GSList *list, *rootlist = NULL;
6654 g_assert (rank <= 255);
6657 /* bounded only matters for one-dimensional arrays */
6660 image = eclass->image;
6662 if (rank == 1 && !bounded) {
6664 * This case is very frequent not just during compilation because of calls
6665 * from mono_class_from_mono_type (), mono_array_new (),
6666 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6668 mono_os_mutex_lock (&image->szarray_cache_lock);
6669 if (!image->szarray_cache)
6670 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6671 klass = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6672 mono_os_mutex_unlock (&image->szarray_cache_lock);
6676 mono_loader_lock ();
6678 mono_loader_lock ();
6680 if (!image->array_cache)
6681 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6683 if ((rootlist = list = (GSList *)g_hash_table_lookup (image->array_cache, eclass))) {
6684 for (; list; list = list->next) {
6685 klass = (MonoClass *)list->data;
6686 if ((klass->rank == rank) && (klass->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6687 mono_loader_unlock ();
6694 parent = mono_defaults.array_class;
6695 if (!parent->inited)
6696 mono_class_init (parent);
6698 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassArray));
6700 klass->image = image;
6701 klass->name_space = eclass->name_space;
6702 klass->class_kind = MONO_CLASS_ARRAY;
6704 nsize = strlen (eclass->name);
6705 name = (char *)g_malloc (nsize + 2 + rank + 1);
6706 memcpy (name, eclass->name, nsize);
6709 memset (name + nsize + 1, ',', rank - 1);
6711 name [nsize + rank] = '*';
6712 name [nsize + rank + bounded] = ']';
6713 name [nsize + rank + bounded + 1] = 0;
6714 klass->name = mono_image_strdup (image, name);
6717 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6719 classes_size += sizeof (MonoClassArray);
6720 ++class_array_count;\
6722 klass->type_token = 0;
6723 klass->parent = parent;
6724 klass->instance_size = mono_class_instance_size (klass->parent);
6726 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6727 /*Arrays of those two types are invalid.*/
6728 MonoError prepared_error;
6729 mono_error_init (&prepared_error);
6730 mono_error_set_invalid_program (&prepared_error, "Arrays of void or System.TypedReference types are invalid.");
6731 mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6732 mono_error_cleanup (&prepared_error);
6733 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6734 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6735 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6736 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6738 /* element_size -1 is ok as this is not an instantitable type*/
6739 klass->sizes.element_size = -1;
6741 klass->sizes.element_size = mono_class_array_element_size (eclass);
6743 mono_class_setup_supertypes (klass);
6745 if (mono_class_is_ginst (eclass))
6746 mono_class_init (eclass);
6747 mono_class_init_sizes (eclass);
6748 mono_class_set_type_load_failure_causedby_class (klass, eclass, "Could not load array element type");
6749 /*FIXME we fail the array type, but we have to let other fields be set.*/
6751 klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6755 if (eclass->enumtype)
6756 klass->cast_class = eclass->element_class;
6758 klass->cast_class = eclass;
6760 switch (klass->cast_class->byval_arg.type) {
6762 klass->cast_class = mono_defaults.byte_class;
6765 klass->cast_class = mono_defaults.int16_class;
6768 #if SIZEOF_VOID_P == 4
6772 klass->cast_class = mono_defaults.int32_class;
6775 #if SIZEOF_VOID_P == 8
6779 klass->cast_class = mono_defaults.int64_class;
6785 klass->element_class = eclass;
6787 if ((rank > 1) || bounded) {
6788 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6789 klass->byval_arg.type = MONO_TYPE_ARRAY;
6790 klass->byval_arg.data.array = at;
6791 at->eklass = eclass;
6793 /* FIXME: complete.... */
6795 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6796 klass->byval_arg.data.klass = eclass;
6798 klass->this_arg = klass->byval_arg;
6799 klass->this_arg.byref = 1;
6801 //WTF was this? it's wrong
6802 // klass->generic_container = eclass->generic_container;
6804 if (rank == 1 && !bounded) {
6805 MonoClass *prev_class;
6807 mono_os_mutex_lock (&image->szarray_cache_lock);
6808 prev_class = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6810 /* Someone got in before us */
6813 g_hash_table_insert (image->szarray_cache, eclass, klass);
6814 mono_os_mutex_unlock (&image->szarray_cache_lock);
6816 list = g_slist_append (rootlist, klass);
6817 g_hash_table_insert (image->array_cache, eclass, list);
6820 mono_loader_unlock ();
6822 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6828 * mono_array_class_get:
6829 * @element_class: element class
6830 * @rank: the dimension of the array class
6832 * Returns: A class object describing the array with element type @element_type and
6836 mono_array_class_get (MonoClass *eclass, guint32 rank)
6838 return mono_bounded_array_class_get (eclass, rank, FALSE);
6842 * mono_class_instance_size:
6845 * Use to get the size of a class in bytes.
6847 * Returns: The size of an object instance
6850 mono_class_instance_size (MonoClass *klass)
6852 if (!klass->size_inited)
6853 mono_class_init_sizes (klass);
6855 return klass->instance_size;
6859 * mono_class_min_align:
6862 * Use to get the computed minimum alignment requirements for the specified class.
6864 * Returns: minimum alignment requirements
6867 mono_class_min_align (MonoClass *klass)
6869 if (!klass->size_inited)
6870 mono_class_init_sizes (klass);
6872 return klass->min_align;
6876 * mono_class_value_size:
6879 * This function is used for value types, and return the
6880 * space and the alignment to store that kind of value object.
6882 * Returns: the size of a value of kind @klass
6885 mono_class_value_size (MonoClass *klass, guint32 *align)
6889 /* fixme: check disable, because we still have external revereces to
6890 * mscorlib and Dummy Objects
6892 /*g_assert (klass->valuetype);*/
6894 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6897 *align = klass->min_align;
6903 * mono_class_data_size:
6906 * Returns: The size of the static class data
6909 mono_class_data_size (MonoClass *klass)
6912 mono_class_init (klass);
6913 /* This can happen with dynamically created types */
6914 if (!klass->size_inited)
6915 mono_class_init_sizes (klass);
6917 /* in arrays, sizes.class_size is unioned with element_size
6918 * and arrays have no static fields
6922 return klass->sizes.class_size;
6926 * Auxiliary routine to mono_class_get_field
6928 * Takes a field index instead of a field token.
6930 static MonoClassField *
6931 mono_class_get_field_idx (MonoClass *klass, int idx)
6933 mono_class_setup_fields (klass);
6934 if (mono_class_has_failure (klass))
6938 if (klass->image->uncompressed_metadata) {
6940 * klass->field.first points to the FieldPtr table, while idx points into the
6941 * Field table, so we have to do a search.
6943 /*FIXME this is broken for types with multiple fields with the same name.*/
6944 const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6947 for (i = 0; i < klass->field.count; ++i)
6948 if (mono_field_get_name (&klass->fields [i]) == name)
6949 return &klass->fields [i];
6950 g_assert_not_reached ();
6952 if (klass->field.count) {
6953 if ((idx >= klass->field.first) && (idx < klass->field.first + klass->field.count)){
6954 return &klass->fields [idx - klass->field.first];
6958 klass = klass->parent;
6964 * mono_class_get_field:
6965 * @class: the class to lookup the field.
6966 * @field_token: the field token
6968 * Returns: A MonoClassField representing the type and offset of
6969 * the field, or a NULL value if the field does not belong to this
6973 mono_class_get_field (MonoClass *klass, guint32 field_token)
6975 int idx = mono_metadata_token_index (field_token);
6977 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6979 return mono_class_get_field_idx (klass, idx - 1);
6983 * mono_class_get_field_from_name:
6984 * @klass: the class to lookup the field.
6985 * @name: the field name
6987 * Search the class @klass and it's parents for a field with the name @name.
6989 * Returns: The MonoClassField pointer of the named field or NULL
6992 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6994 return mono_class_get_field_from_name_full (klass, name, NULL);
6998 * mono_class_get_field_from_name_full:
6999 * @klass: the class to lookup the field.
7000 * @name: the field name
7001 * @type: the type of the fields. This optional.
7003 * Search the class @klass and it's parents for a field with the name @name and type @type.
7005 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
7006 * of its generic type definition.
7008 * Returns: The MonoClassField pointer of the named field or NULL
7011 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
7015 mono_class_setup_fields (klass);
7016 if (mono_class_has_failure (klass))
7020 for (i = 0; i < klass->field.count; ++i) {
7021 MonoClassField *field = &klass->fields [i];
7023 if (strcmp (name, mono_field_get_name (field)) != 0)
7027 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
7028 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
7033 klass = klass->parent;
7039 * mono_class_get_field_token:
7040 * @field: the field we need the token of
7042 * Get the token of a field. Note that the tokesn is only valid for the image
7043 * the field was loaded from. Don't use this function for fields in dynamic types.
7045 * Returns: The token representing the field in the image it was loaded from.
7048 mono_class_get_field_token (MonoClassField *field)
7050 MonoClass *klass = field->parent;
7053 mono_class_setup_fields (klass);
7058 for (i = 0; i < klass->field.count; ++i) {
7059 if (&klass->fields [i] == field) {
7060 int idx = klass->field.first + i + 1;
7062 if (klass->image->uncompressed_metadata)
7063 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
7064 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
7067 klass = klass->parent;
7070 g_assert_not_reached ();
7075 mono_field_get_index (MonoClassField *field)
7077 int index = field - field->parent->fields;
7079 g_assert (index >= 0 && index < field->parent->field.count);
7085 * mono_class_get_field_default_value:
7087 * Return the default value of the field as a pointer into the metadata blob.
7090 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
7093 guint32 constant_cols [MONO_CONSTANT_SIZE];
7095 MonoClass *klass = field->parent;
7097 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7099 if (!klass->ext || !klass->ext->field_def_values) {
7100 MonoFieldDefaultValue *def_values;
7102 mono_class_alloc_ext (klass);
7104 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
7106 mono_image_lock (klass->image);
7107 mono_memory_barrier ();
7108 if (!klass->ext->field_def_values)
7109 klass->ext->field_def_values = def_values;
7110 mono_image_unlock (klass->image);
7113 field_index = mono_field_get_index (field);
7115 if (!klass->ext->field_def_values [field_index].data) {
7116 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7120 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7122 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7123 klass->ext->field_def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7124 klass->ext->field_def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7127 *def_type = klass->ext->field_def_values [field_index].def_type;
7128 return klass->ext->field_def_values [field_index].data;
7132 mono_property_get_index (MonoProperty *prop)
7134 int index = prop - prop->parent->ext->properties;
7136 g_assert (index >= 0 && index < prop->parent->ext->property.count);
7142 * mono_class_get_property_default_value:
7144 * Return the default value of the field as a pointer into the metadata blob.
7147 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7150 guint32 constant_cols [MONO_CONSTANT_SIZE];
7151 MonoClass *klass = property->parent;
7153 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7155 * We don't cache here because it is not used by C# so it's quite rare, but
7156 * we still do the lookup in klass->ext because that is where the data
7157 * is stored for dynamic assemblies.
7160 if (image_is_dynamic (klass->image)) {
7161 int prop_index = mono_property_get_index (property);
7162 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
7163 *def_type = klass->ext->prop_def_values [prop_index].def_type;
7164 return klass->ext->prop_def_values [prop_index].data;
7168 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7172 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7173 *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7174 return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7178 mono_class_get_event_token (MonoEvent *event)
7180 MonoClass *klass = event->parent;
7185 for (i = 0; i < klass->ext->event.count; ++i) {
7186 if (&klass->ext->events [i] == event)
7187 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
7190 klass = klass->parent;
7193 g_assert_not_reached ();
7198 * mono_class_get_property_from_name:
7200 * @name: name of the property to lookup in the specified class
7202 * Use this method to lookup a property in a class
7203 * Returns: the MonoProperty with the given name, or NULL if the property
7204 * does not exist on the @klass.
7207 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7211 gpointer iter = NULL;
7212 while ((p = mono_class_get_properties (klass, &iter))) {
7213 if (! strcmp (name, p->name))
7216 klass = klass->parent;
7222 * mono_class_get_property_token:
7223 * @prop: MonoProperty to query
7225 * Returns: The ECMA token for the specified property.
7228 mono_class_get_property_token (MonoProperty *prop)
7230 MonoClass *klass = prop->parent;
7234 gpointer iter = NULL;
7235 while ((p = mono_class_get_properties (klass, &iter))) {
7236 if (&klass->ext->properties [i] == prop)
7237 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
7241 klass = klass->parent;
7244 g_assert_not_reached ();
7249 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7251 const char *name, *nspace;
7252 if (image_is_dynamic (image))
7253 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7255 switch (type_token & 0xff000000){
7256 case MONO_TOKEN_TYPE_DEF: {
7257 guint32 cols [MONO_TYPEDEF_SIZE];
7258 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7259 guint tidx = mono_metadata_token_index (type_token);
7261 if (tidx > tt->rows)
7262 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7264 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7265 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7266 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7267 if (strlen (nspace) == 0)
7268 return g_strdup_printf ("%s", name);
7270 return g_strdup_printf ("%s.%s", nspace, name);
7273 case MONO_TOKEN_TYPE_REF: {
7275 guint32 cols [MONO_TYPEREF_SIZE];
7276 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7277 guint tidx = mono_metadata_token_index (type_token);
7280 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7282 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7283 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7284 mono_error_cleanup (&error);
7288 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7289 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7290 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7291 if (strlen (nspace) == 0)
7292 return g_strdup_printf ("%s", name);
7294 return g_strdup_printf ("%s.%s", nspace, name);
7297 case MONO_TOKEN_TYPE_SPEC:
7298 return g_strdup_printf ("Typespec 0x%08x", type_token);
7300 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7305 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7307 if (image_is_dynamic (image))
7308 return g_strdup_printf ("DynamicAssembly %s", image->name);
7310 switch (type_token & 0xff000000){
7311 case MONO_TOKEN_TYPE_DEF:
7312 if (image->assembly)
7313 return mono_stringify_assembly_name (&image->assembly->aname);
7314 else if (image->assembly_name)
7315 return g_strdup (image->assembly_name);
7316 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7317 case MONO_TOKEN_TYPE_REF: {
7319 MonoAssemblyName aname;
7320 guint32 cols [MONO_TYPEREF_SIZE];
7321 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7322 guint32 idx = mono_metadata_token_index (type_token);
7325 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7327 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7328 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7329 mono_error_cleanup (&error);
7332 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7334 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7335 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7336 case MONO_RESOLUTION_SCOPE_MODULE:
7338 return g_strdup ("");
7339 case MONO_RESOLUTION_SCOPE_MODULEREF:
7341 return g_strdup ("");
7342 case MONO_RESOLUTION_SCOPE_TYPEREF:
7344 return g_strdup ("");
7345 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7346 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7347 return mono_stringify_assembly_name (&aname);
7349 g_assert_not_reached ();
7353 case MONO_TOKEN_TYPE_SPEC:
7355 return g_strdup ("");
7357 g_assert_not_reached ();
7364 * mono_class_get_full:
7365 * @image: the image where the class resides
7366 * @type_token: the token for the class
7367 * @context: the generic context used to evaluate generic instantiations in
7368 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7370 * Returns: The MonoClass that represents @type_token in @image
7373 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7377 klass = mono_class_get_checked (image, type_token, &error);
7379 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7380 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7382 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7388 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7392 mono_error_init (error);
7393 klass = mono_class_get_checked (image, type_token, error);
7395 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7396 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7401 * mono_class_get_checked:
7402 * @image: the image where the class resides
7403 * @type_token: the token for the class
7404 * @error: error object to return any error
7406 * Returns: The MonoClass that represents @type_token in @image, or NULL on error.
7409 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7411 MonoClass *klass = NULL;
7413 mono_error_init (error);
7415 if (image_is_dynamic (image)) {
7416 int table = mono_metadata_token_table (type_token);
7418 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7419 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7422 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
7426 switch (type_token & 0xff000000){
7427 case MONO_TOKEN_TYPE_DEF:
7428 klass = mono_class_create_from_typedef (image, type_token, error);
7430 case MONO_TOKEN_TYPE_REF:
7431 klass = mono_class_from_typeref_checked (image, type_token, error);
7433 case MONO_TOKEN_TYPE_SPEC:
7434 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7437 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7441 /* Generic case, should be avoided for when a better error is possible. */
7442 if (!klass && mono_error_ok (error)) {
7443 char *name = mono_class_name_from_token (image, type_token);
7444 char *assembly = mono_assembly_name_from_token (image, type_token);
7445 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7453 * mono_type_get_checked:
7454 * @image: the image where the type resides
7455 * @type_token: the token for the type
7456 * @context: the generic context used to evaluate generic instantiations in
7457 * @error: Error handling context
7459 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7461 * Returns: The MonoType that represents @type_token in @image
7464 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7466 MonoType *type = NULL;
7467 gboolean inflated = FALSE;
7469 mono_error_init (error);
7471 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7472 if (image_is_dynamic (image)) {
7473 MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
7474 return_val_if_nok (error, NULL);
7475 return mono_class_get_type (klass);
7478 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7479 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7486 return mono_class_get_type (klass);
7489 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7496 MonoType *tmp = type;
7497 type = mono_class_get_type (mono_class_from_mono_type (type));
7498 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7499 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7500 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7502 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7504 if (type->type != tmp->type)
7507 mono_metadata_free_type (tmp);
7514 * @image: image where the class token will be looked up.
7515 * @type_token: a type token from the image
7517 * Returns the MonoClass with the given @type_token on the @image
7520 mono_class_get (MonoImage *image, guint32 type_token)
7522 return mono_class_get_full (image, type_token, NULL);
7526 * mono_image_init_name_cache:
7528 * Initializes the class name cache stored in image->name_cache.
7530 * LOCKING: Acquires the corresponding image lock.
7533 mono_image_init_name_cache (MonoImage *image)
7535 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7536 guint32 cols [MONO_TYPEDEF_SIZE];
7539 guint32 i, visib, nspace_index;
7540 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7542 if (image->name_cache)
7545 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7547 if (image_is_dynamic (image)) {
7548 mono_image_lock (image);
7549 if (image->name_cache) {
7550 /* Somebody initialized it before us */
7551 g_hash_table_destroy (the_name_cache);
7553 mono_atomic_store_release (&image->name_cache, the_name_cache);
7555 mono_image_unlock (image);
7559 /* Temporary hash table to avoid lookups in the nspace_table */
7560 name_cache2 = g_hash_table_new (NULL, NULL);
7562 for (i = 1; i <= t->rows; ++i) {
7563 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7564 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7566 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7567 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7569 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7571 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7572 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7574 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7575 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7576 if (!nspace_table) {
7577 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7578 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7579 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7582 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7585 /* Load type names from EXPORTEDTYPES table */
7587 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7588 guint32 cols [MONO_EXP_TYPE_SIZE];
7591 for (i = 0; i < t->rows; ++i) {
7592 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7594 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7595 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7599 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7600 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7602 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7603 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7604 if (!nspace_table) {
7605 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7606 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7607 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7610 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7614 g_hash_table_destroy (name_cache2);
7616 mono_image_lock (image);
7617 if (image->name_cache) {
7618 /* Somebody initialized it before us */
7619 g_hash_table_destroy (the_name_cache);
7621 mono_atomic_store_release (&image->name_cache, the_name_cache);
7623 mono_image_unlock (image);
7626 /*FIXME Only dynamic assemblies should allow this operation.*/
7628 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7629 const char *name, guint32 index)
7631 GHashTable *nspace_table;
7632 GHashTable *name_cache;
7635 mono_image_init_name_cache (image);
7636 mono_image_lock (image);
7638 name_cache = image->name_cache;
7639 if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7640 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7641 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7644 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7645 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7647 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7649 mono_image_unlock (image);
7658 find_nocase (gpointer key, gpointer value, gpointer user_data)
7660 char *name = (char*)key;
7661 FindUserData *data = (FindUserData*)user_data;
7663 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7664 data->value = value;
7668 * mono_class_from_name_case:
7669 * @image: The MonoImage where the type is looked up in
7670 * @name_space: the type namespace
7671 * @name: the type short name.
7672 * @deprecated: use the mono_class_from_name_case_checked variant instead.
7674 * Obtains a MonoClass with a given namespace and a given name which
7675 * is located in the given MonoImage. The namespace and name
7676 * lookups are case insensitive.
7679 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7682 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7683 mono_error_cleanup (&error);
7689 * mono_class_from_name_case:
7690 * @image: The MonoImage where the type is looked up in
7691 * @name_space: the type namespace
7692 * @name: the type short name.
7695 * Obtains a MonoClass with a given namespace and a given name which
7696 * is located in the given MonoImage. The namespace and name
7697 * lookups are case insensitive.
7699 * Returns: The MonoClass if the given namespace and name were found, or NULL if it
7700 * was not found. The @error object will contain information about the problem
7704 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7706 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7707 guint32 cols [MONO_TYPEDEF_SIZE];
7712 mono_error_init (error);
7714 if (image_is_dynamic (image)) {
7716 FindUserData user_data;
7718 mono_image_init_name_cache (image);
7719 mono_image_lock (image);
7721 user_data.key = name_space;
7722 user_data.value = NULL;
7723 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7725 if (user_data.value) {
7726 GHashTable *nspace_table = (GHashTable*)user_data.value;
7728 user_data.key = name;
7729 user_data.value = NULL;
7731 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7733 if (user_data.value)
7734 token = GPOINTER_TO_UINT (user_data.value);
7737 mono_image_unlock (image);
7740 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7746 /* add a cache if needed */
7747 for (i = 1; i <= t->rows; ++i) {
7748 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7749 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7751 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7752 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7754 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7756 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7757 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7758 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7759 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7765 return_nested_in (MonoClass *klass, char *nested)
7768 char *s = strchr (nested, '/');
7769 gpointer iter = NULL;
7776 while ((found = mono_class_get_nested_types (klass, &iter))) {
7777 if (strcmp (found->name, nested) == 0) {
7779 return return_nested_in (found, s);
7787 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7789 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7790 MonoImage *file_image;
7794 mono_error_init (error);
7797 * The EXPORTEDTYPES table only contains public types, so have to search the
7799 * Note: image->modules contains the contents of the MODULEREF table, while
7800 * the real module list is in the FILE table.
7802 for (i = 0; i < file_table->rows; i++) {
7803 guint32 cols [MONO_FILE_SIZE];
7804 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7805 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7808 file_image = mono_image_load_file_for_image_checked (image, i + 1, error);
7810 klass = mono_class_from_name_checked (file_image, name_space, name, error);
7811 if (klass || !is_ok (error))
7820 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7822 GHashTable *nspace_table;
7823 MonoImage *loaded_image;
7830 mono_error_init (error);
7832 // Checking visited images avoids stack overflows when cyclic references exist.
7833 if (g_hash_table_lookup (visited_images, image))
7836 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7838 if ((nested = strchr (name, '/'))) {
7839 int pos = nested - name;
7840 int len = strlen (name);
7843 memcpy (buf, name, len + 1);
7845 nested = buf + pos + 1;
7849 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7850 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7851 gboolean res = get_class_from_name (image, name_space, name, &klass);
7854 klass = search_modules (image, name_space, name, error);
7859 return klass ? return_nested_in (klass, nested) : NULL;
7865 mono_image_init_name_cache (image);
7866 mono_image_lock (image);
7868 nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7871 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7873 mono_image_unlock (image);
7875 if (!token && image_is_dynamic (image) && image->modules) {
7876 /* Search modules as well */
7877 for (i = 0; i < image->module_count; ++i) {
7878 MonoImage *module = image->modules [i];
7880 klass = mono_class_from_name_checked (module, name_space, name, error);
7881 if (klass || !is_ok (error))
7887 klass = search_modules (image, name_space, name, error);
7888 if (klass || !is_ok (error))
7893 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7894 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7895 guint32 cols [MONO_EXP_TYPE_SIZE];
7898 idx = mono_metadata_token_index (token);
7900 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7902 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7903 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7904 loaded_image = mono_assembly_load_module_checked (image->assembly, impl >> MONO_IMPLEMENTATION_BITS, error);
7907 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7909 return klass ? return_nested_in (klass, nested) : NULL;
7911 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7912 guint32 assembly_idx;
7914 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7916 mono_assembly_load_reference (image, assembly_idx - 1);
7917 g_assert (image->references [assembly_idx - 1]);
7918 if (image->references [assembly_idx - 1] == (gpointer)-1)
7920 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
7922 return klass ? return_nested_in (klass, nested) : NULL;
7925 g_assert_not_reached ();
7929 token = MONO_TOKEN_TYPE_DEF | token;
7931 klass = mono_class_get_checked (image, token, error);
7933 return return_nested_in (klass, nested);
7938 * mono_class_from_name_checked:
7939 * @image: The MonoImage where the type is looked up in
7940 * @name_space: the type namespace
7941 * @name: the type short name.
7943 * Obtains a MonoClass with a given namespace and a given name which
7944 * is located in the given MonoImage.
7946 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
7947 * set if the class was not found or it will return NULL and set the error if there was a loading error.
7950 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7953 GHashTable *visited_images;
7955 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7957 klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
7959 g_hash_table_destroy (visited_images);
7965 * mono_class_from_name:
7966 * @image: The MonoImage where the type is looked up in
7967 * @name_space: the type namespace
7968 * @name: the type short name.
7970 * Obtains a MonoClass with a given namespace and a given name which
7971 * is located in the given MonoImage.
7973 * To reference nested classes, use the "/" character as a separator.
7974 * For example use "Foo/Bar" to reference the class Bar that is nested
7975 * inside Foo, like this: "class Foo { class Bar {} }".
7978 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7983 klass = mono_class_from_name_checked (image, name_space, name, &error);
7984 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
7990 * mono_class_load_from_name:
7991 * @image: The MonoImage where the type is looked up in
7992 * @name_space: the type namespace
7993 * @name: the type short name.
7995 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
7996 * This function should be used by the runtime for critical types to which there's no way to recover but crash
7997 * If they are missing. Thing of System.Object or System.String.
8000 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
8005 klass = mono_class_from_name_checked (image, name_space, name, &error);
8007 g_error ("Runtime critical type %s.%s not found", name_space, name);
8008 if (!mono_error_ok (&error))
8009 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8014 * mono_class_try_load_from_name:
8015 * @image: The MonoImage where the type is looked up in
8016 * @name_space: the type namespace
8017 * @name: the type short name.
8019 * This function tries to load a type, returning the class was found or NULL otherwise.
8020 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
8022 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
8023 * a type that we would otherwise assume to be available but was not due some error.
8027 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
8032 klass = mono_class_from_name_checked (image, name_space, name, &error);
8033 if (!mono_error_ok (&error))
8034 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8040 * mono_class_is_subclass_of:
8041 * @klass: class to probe if it is a subclass of another one
8042 * @klassc: the class we suspect is the base class
8043 * @check_interfaces: whether we should perform interface checks
8045 * This method determines whether @klass is a subclass of @klassc.
8047 * If the @check_interfaces flag is set, then if @klassc is an interface
8048 * this method return TRUE if the @klass implements the interface or
8049 * if @klass is an interface, if one of its base classes is @klass.
8051 * If @check_interfaces is false then, then if @klass is not an interface
8052 * then it returns TRUE if the @klass is a subclass of @klassc.
8054 * if @klass is an interface and @klassc is System.Object, then this function
8059 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
8060 gboolean check_interfaces)
8062 /* FIXME test for interfaces with variant generic arguments */
8063 mono_class_init (klass);
8064 mono_class_init (klassc);
8066 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
8067 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
8069 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
8072 for (i = 0; i < klass->interface_count; i ++) {
8073 MonoClass *ic = klass->interfaces [i];
8078 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
8083 * MS.NET thinks interfaces are a subclass of Object, so we think it as
8086 if (klassc == mono_defaults.object_class)
8093 mono_type_is_generic_argument (MonoType *type)
8095 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
8099 mono_class_has_variant_generic_params (MonoClass *klass)
8102 MonoGenericContainer *container;
8104 if (!mono_class_is_ginst (klass))
8107 container = mono_class_get_generic_container (mono_class_get_generic_class (klass)->container_class);
8109 for (i = 0; i < container->type_argc; ++i)
8110 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8117 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8119 if (target == candidate)
8122 if (check_for_reference_conv &&
8123 mono_type_is_generic_argument (&target->byval_arg) &&
8124 mono_type_is_generic_argument (&candidate->byval_arg)) {
8125 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8126 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8128 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8131 if (!mono_class_is_assignable_from (target, candidate))
8137 * @container the generic container from the GTD
8138 * @klass: the class to be assigned to
8139 * @oklass: the source class
8141 * Both @klass and @oklass must be instances of the same generic interface.
8143 * Returns: TRUE if @klass can be assigned to a @klass variable
8146 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8149 MonoType **klass_argv, **oklass_argv;
8150 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8151 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8153 if (klass == oklass)
8156 /*Viable candidates are instances of the same generic interface*/
8157 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8160 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8161 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8163 for (j = 0; j < container->type_argc; ++j) {
8164 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8165 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8167 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8171 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8172 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8174 if (param1_class != param2_class) {
8175 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8176 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8178 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8179 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8189 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8191 MonoGenericParam *gparam, *ogparam;
8192 MonoGenericParamInfo *tinfo, *cinfo;
8193 MonoClass **candidate_class;
8194 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8197 if (target == candidate)
8199 if (target->byval_arg.type != candidate->byval_arg.type)
8202 gparam = target->byval_arg.data.generic_param;
8203 ogparam = candidate->byval_arg.data.generic_param;
8204 tinfo = mono_generic_param_info (gparam);
8205 cinfo = mono_generic_param_info (ogparam);
8207 class_constraint_satisfied = FALSE;
8208 valuetype_constraint_satisfied = FALSE;
8210 /*candidate must have a super set of target's special constraints*/
8211 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8212 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8214 if (cinfo->constraints) {
8215 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8216 MonoClass *cc = *candidate_class;
8218 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8219 class_constraint_satisfied = TRUE;
8220 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8221 valuetype_constraint_satisfied = TRUE;
8224 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8225 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8227 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8229 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8231 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8232 valuetype_constraint_satisfied)) {
8237 /*candidate type constraints must be a superset of target's*/
8238 if (tinfo->constraints) {
8239 MonoClass **target_class;
8240 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8241 MonoClass *tc = *target_class;
8244 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8245 * check it's constraints since it satisfy the constraint by itself.
8247 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8250 if (!cinfo->constraints)
8253 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8254 MonoClass *cc = *candidate_class;
8256 if (mono_class_is_assignable_from (tc, cc))
8260 * This happens when we have the following:
8262 * Bar<K> where K : IFace
8263 * Foo<T, U> where T : U where U : IFace
8265 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8268 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8269 if (mono_gparam_is_assignable_from (target, cc))
8273 if (!*candidate_class)
8278 /*candidate itself must have a constraint that satisfy target*/
8279 if (cinfo->constraints) {
8280 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8281 MonoClass *cc = *candidate_class;
8282 if (mono_class_is_assignable_from (target, cc))
8290 * mono_class_is_assignable_from:
8291 * @klass: the class to be assigned to
8292 * @oklass: the source class
8294 * Returns: TRUE if an instance of object oklass can be assigned to an
8295 * instance of object @klass
8298 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8301 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8303 mono_class_init (klass);
8305 if (!oklass->inited)
8306 mono_class_init (oklass);
8308 if (mono_class_has_failure (klass) || mono_class_has_failure (oklass))
8311 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8312 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8314 return mono_gparam_is_assignable_from (klass, oklass);
8317 if (MONO_CLASS_IS_INTERFACE (klass)) {
8318 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8319 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8320 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8324 for (i = 0; constraints [i]; ++i) {
8325 if (mono_class_is_assignable_from (klass, constraints [i]))
8333 /* interface_offsets might not be set for dynamic classes */
8334 if (oklass->ref_info_handle && !oklass->interface_bitmap) {
8336 * oklass might be a generic type parameter but they have
8337 * interface_offsets set.
8339 gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8340 if (!is_ok (&error)) {
8341 mono_error_cleanup (&error);
8346 if (!oklass->interface_bitmap)
8347 /* Happens with generic instances of not-yet created dynamic types */
8349 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8352 if (mono_class_has_variant_generic_params (klass)) {
8354 mono_class_setup_interfaces (oklass, &error);
8355 if (!mono_error_ok (&error)) {
8356 mono_error_cleanup (&error);
8360 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8361 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8362 MonoClass *iface = oklass->interfaces_packed [i];
8364 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8369 } else if (klass->delegate) {
8370 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8372 }else if (klass->rank) {
8373 MonoClass *eclass, *eoclass;
8375 if (oklass->rank != klass->rank)
8378 /* vectors vs. one dimensional arrays */
8379 if (oklass->byval_arg.type != klass->byval_arg.type)
8382 eclass = klass->cast_class;
8383 eoclass = oklass->cast_class;
8386 * a is b does not imply a[] is b[] when a is a valuetype, and
8387 * b is a reference type.
8390 if (eoclass->valuetype) {
8391 if ((eclass == mono_defaults.enum_class) ||
8392 (eclass == mono_defaults.enum_class->parent) ||
8393 (eclass == mono_defaults.object_class))
8397 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8398 } else if (mono_class_is_nullable (klass)) {
8399 if (mono_class_is_nullable (oklass))
8400 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8402 return mono_class_is_assignable_from (klass->cast_class, oklass);
8403 } else if (klass == mono_defaults.object_class)
8406 return mono_class_has_parent (oklass, klass);
8409 /*Check if @oklass is variant compatible with @klass.*/
8411 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8414 MonoType **klass_argv, **oklass_argv;
8415 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8416 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8418 /*Viable candidates are instances of the same generic interface*/
8419 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8422 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8423 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8425 for (j = 0; j < container->type_argc; ++j) {
8426 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8427 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8429 if (param1_class->valuetype != param2_class->valuetype)
8433 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8434 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8436 if (param1_class != param2_class) {
8437 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8438 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8440 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8441 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8449 /*Check if @candidate implements the interface @target*/
8451 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8455 gboolean is_variant = mono_class_has_variant_generic_params (target);
8457 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8458 if (mono_class_is_variant_compatible_slow (target, candidate))
8463 if (candidate == target)
8466 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8467 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8468 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (candidate);
8470 if (tb && tb->interfaces) {
8471 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8472 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8473 MonoClass *iface_class;
8475 /* we can't realize the type here since it can do pretty much anything. */
8478 iface_class = mono_class_from_mono_type (iface->type);
8479 if (iface_class == target)
8481 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8483 if (mono_class_implement_interface_slow (target, iface_class))
8488 /*setup_interfaces don't mono_class_init anything*/
8489 /*FIXME this doesn't handle primitive type arrays.
8490 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8491 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8493 mono_class_setup_interfaces (candidate, &error);
8494 if (!mono_error_ok (&error)) {
8495 mono_error_cleanup (&error);
8499 for (i = 0; i < candidate->interface_count; ++i) {
8500 if (candidate->interfaces [i] == target)
8503 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8506 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8510 candidate = candidate->parent;
8511 } while (candidate);
8517 * Check if @oklass can be assigned to @klass.
8518 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8521 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8523 if (candidate == target)
8525 if (target == mono_defaults.object_class)
8528 if (mono_class_has_parent (candidate, target))
8531 /*If target is not an interface there is no need to check them.*/
8532 if (MONO_CLASS_IS_INTERFACE (target))
8533 return mono_class_implement_interface_slow (target, candidate);
8535 if (target->delegate && mono_class_has_variant_generic_params (target))
8536 return mono_class_is_variant_compatible (target, candidate, FALSE);
8539 MonoClass *eclass, *eoclass;
8541 if (target->rank != candidate->rank)
8544 /* vectors vs. one dimensional arrays */
8545 if (target->byval_arg.type != candidate->byval_arg.type)
8548 eclass = target->cast_class;
8549 eoclass = candidate->cast_class;
8552 * a is b does not imply a[] is b[] when a is a valuetype, and
8553 * b is a reference type.
8556 if (eoclass->valuetype) {
8557 if ((eclass == mono_defaults.enum_class) ||
8558 (eclass == mono_defaults.enum_class->parent) ||
8559 (eclass == mono_defaults.object_class))
8563 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8565 /*FIXME properly handle nullables */
8566 /*FIXME properly handle (M)VAR */
8571 * mono_class_get_cctor:
8572 * @klass: A MonoClass pointer
8574 * Returns: The static constructor of @klass if it exists, NULL otherwise.
8577 mono_class_get_cctor (MonoClass *klass)
8579 MonoCachedClassInfo cached_info;
8581 if (image_is_dynamic (klass->image)) {
8583 * has_cctor is not set for these classes because mono_class_init () is
8586 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8589 if (!klass->has_cctor)
8592 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8594 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8595 if (!mono_error_ok (&error))
8596 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8600 if (mono_class_is_ginst (klass) && !klass->methods)
8601 return mono_class_get_inflated_method (klass, mono_class_get_cctor (mono_class_get_generic_class (klass)->container_class));
8603 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8607 * mono_class_get_finalizer:
8608 * @klass: The MonoClass pointer
8610 * Returns: The finalizer method of @klass if it exists, NULL otherwise.
8613 mono_class_get_finalizer (MonoClass *klass)
8615 MonoCachedClassInfo cached_info;
8618 mono_class_init (klass);
8619 if (!mono_class_has_finalizer (klass))
8622 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8624 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8625 if (!mono_error_ok (&error))
8626 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8629 mono_class_setup_vtable (klass);
8630 return klass->vtable [finalize_slot];
8635 * mono_class_needs_cctor_run:
8636 * @klass: the MonoClass pointer
8637 * @caller: a MonoMethod describing the caller
8639 * Determines whenever the class has a static constructor and whenever it
8640 * needs to be called when executing CALLER.
8643 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8647 method = mono_class_get_cctor (klass);
8649 return (method == caller) ? FALSE : TRUE;
8655 * mono_class_array_element_size:
8658 * Returns: The number of bytes an element of type @klass
8659 * uses when stored into an array.
8662 mono_class_array_element_size (MonoClass *klass)
8664 MonoType *type = &klass->byval_arg;
8667 switch (type->type) {
8670 case MONO_TYPE_BOOLEAN:
8674 case MONO_TYPE_CHAR:
8683 case MONO_TYPE_CLASS:
8684 case MONO_TYPE_STRING:
8685 case MONO_TYPE_OBJECT:
8686 case MONO_TYPE_SZARRAY:
8687 case MONO_TYPE_ARRAY:
8688 return sizeof (gpointer);
8693 case MONO_TYPE_VALUETYPE:
8694 if (type->data.klass->enumtype) {
8695 type = mono_class_enum_basetype (type->data.klass);
8696 klass = klass->element_class;
8699 return mono_class_instance_size (klass) - sizeof (MonoObject);
8700 case MONO_TYPE_GENERICINST:
8701 type = &type->data.generic_class->container_class->byval_arg;
8704 case MONO_TYPE_MVAR: {
8707 return mono_type_size (type, &align);
8709 case MONO_TYPE_VOID:
8713 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8719 * mono_array_element_size:
8720 * @ac: pointer to a #MonoArrayClass
8722 * Returns: The size of single array element.
8725 mono_array_element_size (MonoClass *ac)
8727 g_assert (ac->rank);
8728 return ac->sizes.element_size;
8732 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8733 MonoGenericContext *context)
8736 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8737 g_assert (mono_error_ok (&error));
8742 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8743 MonoGenericContext *context, MonoError *error)
8745 mono_error_init (error);
8747 if (image_is_dynamic (image)) {
8748 MonoClass *tmp_handle_class;
8749 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
8751 mono_error_assert_ok (error);
8752 g_assert (tmp_handle_class);
8754 *handle_class = tmp_handle_class;
8756 if (tmp_handle_class == mono_defaults.typehandle_class)
8757 return &((MonoClass*)obj)->byval_arg;
8762 switch (token & 0xff000000) {
8763 case MONO_TOKEN_TYPE_DEF:
8764 case MONO_TOKEN_TYPE_REF:
8765 case MONO_TOKEN_TYPE_SPEC: {
8768 *handle_class = mono_defaults.typehandle_class;
8769 type = mono_type_get_checked (image, token, context, error);
8773 mono_class_init (mono_class_from_mono_type (type));
8774 /* We return a MonoType* as handle */
8777 case MONO_TOKEN_FIELD_DEF: {
8779 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8781 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8785 *handle_class = mono_defaults.fieldhandle_class;
8786 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8790 mono_class_init (klass);
8791 return mono_class_get_field (klass, token);
8793 case MONO_TOKEN_METHOD_DEF:
8794 case MONO_TOKEN_METHOD_SPEC: {
8796 meth = mono_get_method_checked (image, token, NULL, context, error);
8798 *handle_class = mono_defaults.methodhandle_class;
8804 case MONO_TOKEN_MEMBER_REF: {
8805 guint32 cols [MONO_MEMBERREF_SIZE];
8807 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8808 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8809 mono_metadata_decode_blob_size (sig, &sig);
8810 if (*sig == 0x6) { /* it's a field */
8812 MonoClassField *field;
8813 field = mono_field_from_token_checked (image, token, &klass, context, error);
8815 *handle_class = mono_defaults.fieldhandle_class;
8819 meth = mono_get_method_checked (image, token, NULL, context, error);
8821 *handle_class = mono_defaults.methodhandle_class;
8826 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8832 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
8834 MonoClass *handle_class;
8835 mono_error_init (error);
8836 return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
8840 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
8842 return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
8845 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8848 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8850 get_cached_class_info = func;
8854 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8856 if (!get_cached_class_info)
8859 return get_cached_class_info (klass, res);
8863 mono_install_get_class_from_name (MonoGetClassFromName func)
8865 get_class_from_name = func;
8869 * mono_class_get_image:
8871 * Use this method to get the `MonoImage*` where this class came from.
8873 * Returns: The image where this class is defined.
8876 mono_class_get_image (MonoClass *klass)
8878 return klass->image;
8882 * mono_class_get_element_class:
8883 * @klass: the MonoClass to act on
8885 * Use this function to get the element class of an array.
8887 * Returns: The element class of an array.
8890 mono_class_get_element_class (MonoClass *klass)
8892 return klass->element_class;
8896 * mono_class_is_valuetype:
8897 * @klass: the MonoClass to act on
8899 * Use this method to determine if the provided `MonoClass*` represents a value type,
8900 * or a reference type.
8902 * Returns: TRUE if the MonoClass represents a ValueType, FALSE if it represents a reference type.
8905 mono_class_is_valuetype (MonoClass *klass)
8907 return klass->valuetype;
8911 * mono_class_is_enum:
8912 * @klass: the MonoClass to act on
8914 * Use this function to determine if the provided `MonoClass*` represents an enumeration.
8916 * Returns: TRUE if the MonoClass represents an enumeration.
8919 mono_class_is_enum (MonoClass *klass)
8921 return klass->enumtype;
8925 * mono_class_enum_basetype:
8926 * @klass: the MonoClass to act on
8928 * Use this function to get the underlying type for an enumeration value.
8930 * Returns: The underlying type representation for an enumeration.
8933 mono_class_enum_basetype (MonoClass *klass)
8935 if (klass->element_class == klass)
8936 /* SRE or broken types */
8939 return &klass->element_class->byval_arg;
8943 * mono_class_get_parent
8944 * @klass: the MonoClass to act on
8946 * Returns: The parent class for this class.
8949 mono_class_get_parent (MonoClass *klass)
8951 return klass->parent;
8955 * mono_class_get_nesting_type:
8956 * @klass: the MonoClass to act on
8958 * Use this function to obtain the class that the provided `MonoClass*` is nested on.
8960 * If the return is NULL, this indicates that this class is not nested.
8962 * Returns: The container type where this type is nested or NULL if this type is not a nested type.
8965 mono_class_get_nesting_type (MonoClass *klass)
8967 return klass->nested_in;
8971 * mono_class_get_rank:
8972 * @klass: the MonoClass to act on
8974 * Returns: The rank for the array (the number of dimensions).
8977 mono_class_get_rank (MonoClass *klass)
8983 * mono_class_get_name
8984 * @klass: the MonoClass to act on
8986 * Returns: The name of the class.
8989 mono_class_get_name (MonoClass *klass)
8995 * mono_class_get_namespace:
8996 * @klass: the MonoClass to act on
8998 * Returns: The namespace of the class.
9001 mono_class_get_namespace (MonoClass *klass)
9003 return klass->name_space;
9007 * mono_class_get_type:
9008 * @klass: the MonoClass to act on
9010 * This method returns the internal Type representation for the class.
9012 * Returns: The MonoType from the class.
9015 mono_class_get_type (MonoClass *klass)
9017 return &klass->byval_arg;
9021 * mono_class_get_type_token:
9022 * @klass: the MonoClass to act on
9024 * This method returns type token for the class.
9026 * Returns: The type token for the class.
9029 mono_class_get_type_token (MonoClass *klass)
9031 return klass->type_token;
9035 * mono_class_get_byref_type:
9036 * @klass: the MonoClass to act on
9041 mono_class_get_byref_type (MonoClass *klass)
9043 return &klass->this_arg;
9047 * mono_class_num_fields:
9048 * @klass: the MonoClass to act on
9050 * Returns: The number of static and instance fields in the class.
9053 mono_class_num_fields (MonoClass *klass)
9055 return klass->field.count;
9059 * mono_class_num_methods:
9060 * @klass: the MonoClass to act on
9062 * Returns: The number of methods in the class.
9065 mono_class_num_methods (MonoClass *klass)
9067 return klass->method.count;
9071 * mono_class_num_properties
9072 * @klass: the MonoClass to act on
9074 * Returns: The number of properties in the class.
9077 mono_class_num_properties (MonoClass *klass)
9079 mono_class_setup_properties (klass);
9081 return klass->ext->property.count;
9085 * mono_class_num_events:
9086 * @klass: the MonoClass to act on
9088 * Returns: The number of events in the class.
9091 mono_class_num_events (MonoClass *klass)
9093 mono_class_setup_events (klass);
9095 return klass->ext->event.count;
9099 * mono_class_get_fields:
9100 * @klass: the MonoClass to act on
9102 * This routine is an iterator routine for retrieving the fields in a class.
9104 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9105 * iterate over all of the elements. When no more values are
9106 * available, the return value is NULL.
9108 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
9111 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9113 MonoClassField* field;
9117 mono_class_setup_fields (klass);
9118 if (mono_class_has_failure (klass))
9120 /* start from the first */
9121 if (klass->field.count) {
9122 *iter = &klass->fields [0];
9123 return &klass->fields [0];
9129 field = (MonoClassField *)*iter;
9131 if (field < &klass->fields [klass->field.count]) {
9139 * mono_class_get_methods
9140 * @klass: the MonoClass to act on
9142 * This routine is an iterator routine for retrieving the fields in a class.
9144 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9145 * iterate over all of the elements. When no more values are
9146 * available, the return value is NULL.
9148 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
9151 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9153 MonoMethod** method;
9157 mono_class_setup_methods (klass);
9160 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9161 * FIXME we should better report this error to the caller
9163 if (!klass->methods)
9165 /* start from the first */
9166 if (klass->method.count) {
9167 *iter = &klass->methods [0];
9168 return klass->methods [0];
9174 method = (MonoMethod **)*iter;
9176 if (method < &klass->methods [klass->method.count]) {
9184 * mono_class_get_virtual_methods:
9186 * Iterate over the virtual methods of KLASS.
9188 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9191 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9193 MonoMethod** method;
9196 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9198 mono_class_setup_methods (klass);
9200 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9201 * FIXME we should better report this error to the caller
9203 if (!klass->methods)
9205 /* start from the first */
9206 method = &klass->methods [0];
9208 method = (MonoMethod **)*iter;
9211 while (method < &klass->methods [klass->method.count]) {
9212 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9216 if (method < &klass->methods [klass->method.count]) {
9223 /* Search directly in metadata to avoid calling setup_methods () */
9224 MonoMethod *res = NULL;
9230 start_index = GPOINTER_TO_UINT (*iter);
9233 for (i = start_index; i < klass->method.count; ++i) {
9236 /* klass->method.first points into the methodptr table */
9237 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
9239 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9243 if (i < klass->method.count) {
9245 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9246 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9248 /* Add 1 here so the if (*iter) check fails */
9249 *iter = GUINT_TO_POINTER (i + 1);
9258 * mono_class_get_properties:
9259 * @klass: the MonoClass to act on
9261 * This routine is an iterator routine for retrieving the properties in a class.
9263 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9264 * iterate over all of the elements. When no more values are
9265 * available, the return value is NULL.
9267 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9270 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9272 MonoProperty* property;
9276 mono_class_setup_properties (klass);
9277 /* start from the first */
9278 if (klass->ext->property.count) {
9279 *iter = &klass->ext->properties [0];
9280 return (MonoProperty *)*iter;
9286 property = (MonoProperty *)*iter;
9288 if (property < &klass->ext->properties [klass->ext->property.count]) {
9290 return (MonoProperty *)*iter;
9296 * mono_class_get_events:
9297 * @klass: the MonoClass to act on
9299 * This routine is an iterator routine for retrieving the properties in a class.
9301 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9302 * iterate over all of the elements. When no more values are
9303 * available, the return value is NULL.
9305 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9308 mono_class_get_events (MonoClass* klass, gpointer *iter)
9314 mono_class_setup_events (klass);
9315 /* start from the first */
9316 if (klass->ext->event.count) {
9317 *iter = &klass->ext->events [0];
9318 return (MonoEvent *)*iter;
9324 event = (MonoEvent *)*iter;
9326 if (event < &klass->ext->events [klass->ext->event.count]) {
9328 return (MonoEvent *)*iter;
9334 * mono_class_get_interfaces
9335 * @klass: the MonoClass to act on
9337 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9339 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9340 * iterate over all of the elements. When no more values are
9341 * available, the return value is NULL.
9343 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9346 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9354 mono_class_init (klass);
9355 if (!klass->interfaces_inited) {
9356 mono_class_setup_interfaces (klass, &error);
9357 if (!mono_error_ok (&error)) {
9358 mono_error_cleanup (&error);
9362 /* start from the first */
9363 if (klass->interface_count) {
9364 *iter = &klass->interfaces [0];
9365 return klass->interfaces [0];
9371 iface = (MonoClass **)*iter;
9373 if (iface < &klass->interfaces [klass->interface_count]) {
9381 setup_nested_types (MonoClass *klass)
9384 GList *classes, *nested_classes, *l;
9387 if (klass->nested_classes_inited)
9390 if (!klass->type_token)
9391 klass->nested_classes_inited = TRUE;
9393 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9397 guint32 cols [MONO_NESTED_CLASS_SIZE];
9398 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9399 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9400 if (!mono_error_ok (&error)) {
9401 /*FIXME don't swallow the error message*/
9402 mono_error_cleanup (&error);
9404 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9408 classes = g_list_prepend (classes, nclass);
9410 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9413 mono_class_alloc_ext (klass);
9415 nested_classes = NULL;
9416 for (l = classes; l; l = l->next)
9417 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9418 g_list_free (classes);
9420 mono_image_lock (klass->image);
9422 mono_memory_barrier ();
9423 if (!klass->nested_classes_inited) {
9424 klass->ext->nested_classes = nested_classes;
9425 mono_memory_barrier ();
9426 klass->nested_classes_inited = TRUE;
9429 mono_image_unlock (klass->image);
9433 * mono_class_get_nested_types
9434 * @klass: the MonoClass to act on
9436 * This routine is an iterator routine for retrieving the nested types of a class.
9437 * This works only if @klass is non-generic, or a generic type definition.
9439 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9440 * iterate over all of the elements. When no more values are
9441 * available, the return value is NULL.
9443 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9446 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9452 if (!klass->nested_classes_inited)
9453 setup_nested_types (klass);
9456 /* start from the first */
9457 if (klass->ext && klass->ext->nested_classes) {
9458 *iter = klass->ext->nested_classes;
9459 return (MonoClass *)klass->ext->nested_classes->data;
9461 /* no nested types */
9465 item = (GList *)*iter;
9469 return (MonoClass *)item->data;
9476 * mono_class_is_delegate
9477 * @klass: the MonoClass to act on
9479 * Returns: TRUE if the MonoClass represents a System.Delegate.
9482 mono_class_is_delegate (MonoClass *klass)
9484 return klass->delegate;
9488 * mono_class_implements_interface
9489 * @klass: The MonoClass to act on
9490 * @interface: The interface to check if @klass implements.
9492 * Returns: TRUE if @klass implements @interface.
9495 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9497 return mono_class_is_assignable_from (iface, klass);
9501 * mono_field_get_name:
9502 * @field: the MonoClassField to act on
9504 * Returns: The name of the field.
9507 mono_field_get_name (MonoClassField *field)
9513 * mono_field_get_type:
9514 * @field: the MonoClassField to act on
9516 * Returns: MonoType of the field.
9519 mono_field_get_type (MonoClassField *field)
9522 MonoType *type = mono_field_get_type_checked (field, &error);
9523 if (!mono_error_ok (&error)) {
9524 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9525 mono_error_cleanup (&error);
9532 * mono_field_get_type_checked:
9533 * @field: the MonoClassField to act on
9534 * @error: used to return any erro found while retrieving @field type
9536 * Returns: MonoType of the field.
9539 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9541 mono_error_init (error);
9543 mono_field_resolve_type (field, error);
9548 * mono_field_get_parent:
9549 * @field: the MonoClassField to act on
9551 * Returns: MonoClass where the field was defined.
9554 mono_field_get_parent (MonoClassField *field)
9556 return field->parent;
9560 * mono_field_get_flags;
9561 * @field: the MonoClassField to act on
9563 * The metadata flags for a field are encoded using the
9564 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9566 * Returns: The flags for the field.
9569 mono_field_get_flags (MonoClassField *field)
9572 return mono_field_resolve_flags (field);
9573 return field->type->attrs;
9577 * mono_field_get_offset:
9578 * @field: the MonoClassField to act on
9580 * Returns: The field offset.
9583 mono_field_get_offset (MonoClassField *field)
9585 return field->offset;
9589 mono_field_get_rva (MonoClassField *field)
9593 MonoClass *klass = field->parent;
9594 MonoFieldDefaultValue *field_def_values;
9596 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9598 if (!klass->ext || !klass->ext->field_def_values) {
9599 mono_class_alloc_ext (klass);
9601 field_def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9603 mono_image_lock (klass->image);
9604 if (!klass->ext->field_def_values)
9605 klass->ext->field_def_values = field_def_values;
9606 mono_image_unlock (klass->image);
9609 field_index = mono_field_get_index (field);
9611 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9612 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9614 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9615 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9618 return klass->ext->field_def_values [field_index].data;
9622 * mono_field_get_data:
9623 * @field: the MonoClassField to act on
9625 * Returns: A pointer to the metadata constant value or to the field
9626 * data if it has an RVA flag.
9629 mono_field_get_data (MonoClassField *field)
9631 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9632 MonoTypeEnum def_type;
9634 return mono_class_get_field_default_value (field, &def_type);
9635 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9636 return mono_field_get_rva (field);
9643 * mono_property_get_name:
9644 * @prop: the MonoProperty to act on
9646 * Returns: The name of the property
9649 mono_property_get_name (MonoProperty *prop)
9655 * mono_property_get_set_method
9656 * @prop: the MonoProperty to act on.
9658 * Returns: The setter method of the property (A MonoMethod)
9661 mono_property_get_set_method (MonoProperty *prop)
9667 * mono_property_get_get_method
9668 * @prop: the MonoProperty to act on.
9670 * Returns: The setter method of the property (A MonoMethod)
9673 mono_property_get_get_method (MonoProperty *prop)
9679 * mono_property_get_parent:
9680 * @prop: the MonoProperty to act on.
9682 * Returns: The MonoClass where the property was defined.
9685 mono_property_get_parent (MonoProperty *prop)
9687 return prop->parent;
9691 * mono_property_get_flags:
9692 * @prop: the MonoProperty to act on.
9694 * The metadata flags for a property are encoded using the
9695 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9697 * Returns: The flags for the property.
9700 mono_property_get_flags (MonoProperty *prop)
9706 * mono_event_get_name:
9707 * @event: the MonoEvent to act on
9709 * Returns: The name of the event.
9712 mono_event_get_name (MonoEvent *event)
9718 * mono_event_get_add_method:
9719 * @event: The MonoEvent to act on.
9721 * Returns: The @add' method for the event (a MonoMethod).
9724 mono_event_get_add_method (MonoEvent *event)
9730 * mono_event_get_remove_method:
9731 * @event: The MonoEvent to act on.
9733 * Returns: The @remove method for the event (a MonoMethod).
9736 mono_event_get_remove_method (MonoEvent *event)
9738 return event->remove;
9742 * mono_event_get_raise_method:
9743 * @event: The MonoEvent to act on.
9745 * Returns: The @raise method for the event (a MonoMethod).
9748 mono_event_get_raise_method (MonoEvent *event)
9750 return event->raise;
9754 * mono_event_get_parent:
9755 * @event: the MonoEvent to act on.
9757 * Returns: The MonoClass where the event is defined.
9760 mono_event_get_parent (MonoEvent *event)
9762 return event->parent;
9766 * mono_event_get_flags
9767 * @event: the MonoEvent to act on.
9769 * The metadata flags for an event are encoded using the
9770 * EVENT_* constants. See the tabledefs.h file for details.
9772 * Returns: The flags for the event.
9775 mono_event_get_flags (MonoEvent *event)
9777 return event->attrs;
9781 * mono_class_get_method_from_name:
9782 * @klass: where to look for the method
9783 * @name: name of the method
9784 * @param_count: number of parameters. -1 for any number.
9786 * Obtains a MonoMethod with a given name and number of parameters.
9787 * It only works if there are no multiple signatures for any given method name.
9790 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9792 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9796 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9798 MonoMethod *res = NULL;
9801 /* Search directly in the metadata to avoid calling setup_methods () */
9802 for (i = 0; i < klass->method.count; ++i) {
9804 guint32 cols [MONO_METHOD_SIZE];
9806 MonoMethodSignature *sig;
9808 /* klass->method.first points into the methodptr table */
9809 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9811 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9812 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9814 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9817 if (param_count == -1) {
9821 sig = mono_method_signature_checked (method, &error);
9823 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9826 if (sig->param_count == param_count) {
9837 * mono_class_get_method_from_name_flags:
9838 * @klass: where to look for the method
9839 * @name_space: name of the method
9840 * @param_count: number of parameters. -1 for any number.
9841 * @flags: flags which must be set in the method
9843 * Obtains a MonoMethod with a given name and number of parameters.
9844 * It only works if there are no multiple signatures for any given method name.
9847 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9849 MonoMethod *res = NULL;
9852 mono_class_init (klass);
9854 if (mono_class_is_ginst (klass) && !klass->methods) {
9855 res = mono_class_get_method_from_name_flags (mono_class_get_generic_class (klass)->container_class, name, param_count, flags);
9858 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9859 if (!mono_error_ok (&error))
9860 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9865 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9866 mono_class_setup_methods (klass);
9868 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9869 See mono/tests/array_load_exception.il
9870 FIXME we should better report this error to the caller
9872 if (!klass->methods)
9874 for (i = 0; i < klass->method.count; ++i) {
9875 MonoMethod *method = klass->methods [i];
9877 if (method->name[0] == name [0] &&
9878 !strcmp (name, method->name) &&
9879 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9880 ((method->flags & flags) == flags)) {
9887 res = find_method_in_metadata (klass, name, param_count, flags);
9894 * mono_class_set_failure:
9895 * @klass: class in which the failure was detected
9896 * @ex_type: the kind of exception/error to be thrown (later)
9897 * @ex_data: exception data (specific to each type of exception/error)
9899 * Keep a detected failure informations in the class for later processing.
9900 * Note that only the first failure is kept.
9902 * LOCKING: Acquires the loader lock.
9905 mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error)
9907 g_assert (boxed_error != NULL);
9909 if (mono_class_has_failure (klass))
9912 mono_loader_lock ();
9913 klass->has_failure = 1;
9914 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, boxed_error);
9915 mono_loader_unlock ();
9921 mono_class_has_failure (const MonoClass *klass)
9923 g_assert (klass != NULL);
9924 return klass->has_failure != 0;
9929 * mono_class_set_type_load_failure:
9930 * @klass: class in which the failure was detected
9931 * @fmt: Printf-style error message string.
9933 * Collect detected failure informaion in the class for later processing.
9934 * The error is stored as a MonoErrorBoxed as with mono_error_set_type_load_class ()
9935 * Note that only the first failure is kept.
9937 * Returns FALSE if a failure was already set on the class, or TRUE otherwise.
9939 * LOCKING: Acquires the loader lock.
9942 mono_class_set_type_load_failure (MonoClass *klass, const char * fmt, ...)
9944 MonoError prepare_error;
9947 if (mono_class_has_failure (klass))
9950 mono_error_init (&prepare_error);
9952 va_start (args, fmt);
9953 mono_error_vset_type_load_class (&prepare_error, klass, fmt, args);
9956 MonoErrorBoxed *box = mono_error_box (&prepare_error, klass->image);
9957 mono_error_cleanup (&prepare_error);
9958 return mono_class_set_failure (klass, box);
9962 * mono_class_get_exception_data:
9964 * Return the exception_data property of KLASS.
9966 * LOCKING: Acquires the loader lock.
9969 mono_class_get_exception_data (const MonoClass *klass)
9971 return mono_image_property_lookup (klass->image, (MonoClass*)klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9975 * mono_classes_init:
9977 * Initialize the resources used by this module.
9980 mono_classes_init (void)
9982 mono_os_mutex_init (&classes_mutex);
9984 mono_native_tls_alloc (&setup_fields_tls_id, NULL);
9985 mono_native_tls_alloc (&init_pending_tls_id, NULL);
9987 mono_counters_register ("MonoClassDef count",
9988 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_def_count);
9989 mono_counters_register ("MonoClassGtd count",
9990 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gtd_count);
9991 mono_counters_register ("MonoClassGenericInst count",
9992 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ginst_count);
9993 mono_counters_register ("MonoClassGenericParam count",
9994 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gparam_count);
9995 mono_counters_register ("MonoClassArray count",
9996 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_array_count);
9997 mono_counters_register ("MonoClassPointer count",
9998 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_pointer_count);
9999 mono_counters_register ("Inflated methods size",
10000 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
10001 mono_counters_register ("Inflated classes size",
10002 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
10003 mono_counters_register ("MonoClass size",
10004 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
10005 mono_counters_register ("MonoClassExt size",
10006 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
10008 mono_counters_register ("MonoClassExt count",
10009 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_count);
10013 * mono_classes_cleanup:
10015 * Free the resources used by this module.
10018 mono_classes_cleanup (void)
10020 mono_native_tls_free (setup_fields_tls_id);
10021 mono_native_tls_free (init_pending_tls_id);
10023 if (global_interface_bitset)
10024 mono_bitset_free (global_interface_bitset);
10025 global_interface_bitset = NULL;
10026 mono_os_mutex_destroy (&classes_mutex);
10030 * mono_class_get_exception_for_failure:
10031 * @klass: class in which the failure was detected
10033 * Return a constructed MonoException than the caller can then throw
10034 * using mono_raise_exception - or NULL if no failure is present (or
10035 * doesn't result in an exception).
10038 mono_class_get_exception_for_failure (MonoClass *klass)
10040 if (!mono_class_has_failure (klass))
10042 MonoError unboxed_error;
10043 mono_error_init (&unboxed_error);
10044 mono_error_set_for_class_failure (&unboxed_error, klass);
10045 return mono_error_convert_to_exception (&unboxed_error);
10049 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
10051 outer_klass = mono_class_get_generic_type_definition (outer_klass);
10052 inner_klass = mono_class_get_generic_type_definition (inner_klass);
10054 if (outer_klass == inner_klass)
10056 inner_klass = inner_klass->nested_in;
10057 } while (inner_klass);
10062 mono_class_get_generic_type_definition (MonoClass *klass)
10064 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
10065 return gklass ? gklass->container_class : klass;
10069 * Check if @klass is a subtype of @parent ignoring generic instantiations.
10071 * Generic instantiations are ignored for all super types of @klass.
10073 * Visibility checks ignoring generic instantiations.
10076 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
10079 klass = mono_class_get_generic_type_definition (klass);
10080 parent = mono_class_get_generic_type_definition (parent);
10081 mono_class_setup_supertypes (klass);
10083 for (i = 0; i < klass->idepth; ++i) {
10084 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
10090 * Subtype can only access parent members with family protection if the site object
10091 * is subclass of Subtype. For example:
10092 * class A { protected int x; }
10094 * void valid_access () {
10098 * void invalid_access () {
10105 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
10107 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
10110 if (context_klass == NULL)
10112 /*if access_klass is not member_klass context_klass must be type compat*/
10113 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10119 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10122 if (accessing == accessed)
10124 if (!accessed || !accessing)
10127 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10128 * anywhere so untrusted friends are not safe to access platform's code internals */
10129 if (mono_security_core_clr_enabled ()) {
10130 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10134 mono_assembly_load_friends (accessed);
10135 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10136 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10137 /* Be conservative with checks */
10138 if (!friend_->name)
10140 if (strcmp (accessing->aname.name, friend_->name))
10142 if (friend_->public_key_token [0]) {
10143 if (!accessing->aname.public_key_token [0])
10145 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10154 * If klass is a generic type or if it is derived from a generic type, return the
10155 * MonoClass of the generic definition
10156 * Returns NULL if not found
10159 get_generic_definition_class (MonoClass *klass)
10162 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
10163 if (gklass && gklass->container_class)
10164 return gklass->container_class;
10165 klass = klass->parent;
10171 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10174 for (i = 0; i < ginst->type_argc; ++i) {
10175 MonoType *type = ginst->type_argv[i];
10176 switch (type->type) {
10177 case MONO_TYPE_SZARRAY:
10178 if (!can_access_type (access_klass, type->data.klass))
10181 case MONO_TYPE_ARRAY:
10182 if (!can_access_type (access_klass, type->data.array->eklass))
10185 case MONO_TYPE_PTR:
10186 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10189 case MONO_TYPE_CLASS:
10190 case MONO_TYPE_VALUETYPE:
10191 case MONO_TYPE_GENERICINST:
10192 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10202 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10206 if (access_klass == member_klass)
10209 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10212 if (access_klass->element_class && !access_klass->enumtype)
10213 access_klass = access_klass->element_class;
10215 if (member_klass->element_class && !member_klass->enumtype)
10216 member_klass = member_klass->element_class;
10218 access_level = mono_class_get_flags (member_klass) & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10220 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10223 if (mono_class_is_ginst (member_klass) && !can_access_instantiation (access_klass, mono_class_get_generic_class (member_klass)->context.class_inst))
10226 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10229 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10232 /*Non nested type with nested visibility. We just fail it.*/
10233 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10236 switch (access_level) {
10237 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10238 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10240 case TYPE_ATTRIBUTE_PUBLIC:
10243 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10246 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10247 return is_nesting_type (member_klass, access_klass);
10249 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10250 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10252 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10253 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10255 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10256 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10257 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10259 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10260 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10261 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10266 /* FIXME: check visibility of type, too */
10268 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10270 MonoClass *member_generic_def;
10271 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10274 MonoGenericClass *access_gklass = mono_class_try_get_generic_class (access_klass);
10275 if (((access_gklass && access_gklass->container_class) ||
10276 mono_class_is_gtd (access_klass)) &&
10277 (member_generic_def = get_generic_definition_class (member_klass))) {
10278 MonoClass *access_container;
10280 if (mono_class_is_gtd (access_klass))
10281 access_container = access_klass;
10283 access_container = access_gklass->container_class;
10285 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10289 /* Partition I 8.5.3.2 */
10290 /* the access level values are the same for fields and methods */
10291 switch (access_level) {
10292 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10293 /* same compilation unit */
10294 return access_klass->image == member_klass->image;
10295 case FIELD_ATTRIBUTE_PRIVATE:
10296 return access_klass == member_klass;
10297 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10298 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10299 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10302 case FIELD_ATTRIBUTE_ASSEMBLY:
10303 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10304 case FIELD_ATTRIBUTE_FAMILY:
10305 if (is_valid_family_access (access_klass, member_klass, context_klass))
10308 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10309 if (is_valid_family_access (access_klass, member_klass, context_klass))
10311 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10312 case FIELD_ATTRIBUTE_PUBLIC:
10319 * mono_method_can_access_field:
10320 * @method: Method that will attempt to access the field
10321 * @field: the field to access
10323 * Used to determine if a method is allowed to access the specified field.
10325 * Returns: TRUE if the given @method is allowed to access the @field while following
10326 * the accessibility rules of the CLI.
10329 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10331 /* FIXME: check all overlapping fields */
10332 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10334 MonoClass *nested = method->klass->nested_in;
10336 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10339 nested = nested->nested_in;
10346 * mono_method_can_access_method:
10347 * @method: Method that will attempt to access the other method
10348 * @called: the method that we want to probe for accessibility.
10350 * Used to determine if the @method is allowed to access the specified @called method.
10352 * Returns: TRUE if the given @method is allowed to invoke the @called while following
10353 * the accessibility rules of the CLI.
10356 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10358 method = mono_method_get_method_definition (method);
10359 called = mono_method_get_method_definition (called);
10360 return mono_method_can_access_method_full (method, called, NULL);
10364 * mono_method_can_access_method_full:
10365 * @method: The caller method
10366 * @called: The called method
10367 * @context_klass: The static type on stack of the owner @called object used
10369 * This function must be used with instance calls, as they have more strict family accessibility.
10370 * It can be used with static methods, but context_klass should be NULL.
10372 * Returns: TRUE if caller have proper visibility and acessibility to @called
10375 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10377 /* Wrappers are except from access checks */
10378 if (method->wrapper_type != MONO_WRAPPER_NONE || called->wrapper_type != MONO_WRAPPER_NONE)
10381 MonoClass *access_class = method->klass;
10382 MonoClass *member_class = called->klass;
10383 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10385 MonoClass *nested = access_class->nested_in;
10387 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10390 nested = nested->nested_in;
10397 can = can_access_type (access_class, member_class);
10399 MonoClass *nested = access_class->nested_in;
10401 can = can_access_type (nested, member_class);
10404 nested = nested->nested_in;
10411 if (called->is_inflated) {
10412 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10413 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10422 * mono_method_can_access_field_full:
10423 * @method: The caller method
10424 * @field: The accessed field
10425 * @context_klass: The static type on stack of the owner @field object used
10427 * This function must be used with instance fields, as they have more strict family accessibility.
10428 * It can be used with static fields, but context_klass should be NULL.
10430 * Returns: TRUE if caller have proper visibility and acessibility to @field
10433 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10435 MonoClass *access_class = method->klass;
10436 MonoClass *member_class = field->parent;
10437 /* FIXME: check all overlapping fields */
10438 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10440 MonoClass *nested = access_class->nested_in;
10442 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10445 nested = nested->nested_in;
10452 can = can_access_type (access_class, member_class);
10454 MonoClass *nested = access_class->nested_in;
10456 can = can_access_type (nested, member_class);
10459 nested = nested->nested_in;
10469 * mono_class_can_access_class:
10470 * @source_class: The source class
10471 * @target_class: The accessed class
10473 * This function returns is @target_class is visible to @source_class
10475 * Returns: TRUE if source have proper visibility and acessibility to target
10478 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10480 return can_access_type (source_class, target_class);
10484 * mono_type_is_valid_enum_basetype:
10485 * @type: The MonoType to check
10487 * Returns: TRUE if the type can be used as the basetype of an enum
10489 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10490 switch (type->type) {
10493 case MONO_TYPE_BOOLEAN:
10496 case MONO_TYPE_CHAR:
10510 * mono_class_is_valid_enum:
10511 * @klass: An enum class to be validated
10513 * This method verify the required properties an enum should have.
10515 * Returns: TRUE if the informed enum class is valid
10517 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10518 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10519 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10521 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10522 MonoClassField * field;
10523 gpointer iter = NULL;
10524 gboolean found_base_field = FALSE;
10526 g_assert (klass->enumtype);
10527 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10528 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10532 if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10535 while ((field = mono_class_get_fields (klass, &iter))) {
10536 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10537 if (found_base_field)
10539 found_base_field = TRUE;
10540 if (!mono_type_is_valid_enum_basetype (field->type))
10545 if (!found_base_field)
10548 if (klass->method.count > 0)
10555 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10557 return gklass->context.class_inst == mono_class_get_generic_container (gklass->container_class)->context.class_inst;
10561 * mono_class_setup_interface_id:
10563 * Initializes MonoClass::interface_id if required.
10565 * LOCKING: Acquires the loader lock.
10568 mono_class_setup_interface_id (MonoClass *klass)
10570 mono_loader_lock ();
10571 if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10572 klass->interface_id = mono_get_unique_iid (klass);
10573 mono_loader_unlock ();
10577 * mono_class_alloc_ext:
10579 * Allocate klass->ext if not already done.
10582 mono_class_alloc_ext (MonoClass *klass)
10589 ext = (MonoClassExt *)mono_class_alloc0 (klass, sizeof (MonoClassExt));
10590 mono_image_lock (klass->image);
10591 mono_memory_barrier ();
10594 class_ext_size += sizeof (MonoClassExt);
10596 mono_image_unlock (klass->image);
10600 * mono_class_setup_interfaces:
10602 * Initialize klass->interfaces/interfaces_count.
10603 * LOCKING: Acquires the loader lock.
10604 * This function can fail the type.
10607 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10609 int i, interface_count;
10610 MonoClass **interfaces;
10612 mono_error_init (error);
10614 if (klass->interfaces_inited)
10617 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10618 MonoType *args [1];
10620 /* generic IList, ICollection, IEnumerable */
10621 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10622 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10624 args [0] = &klass->element_class->byval_arg;
10625 interfaces [0] = mono_class_bind_generic_parameters (
10626 mono_defaults.generic_ilist_class, 1, args, FALSE);
10627 if (interface_count > 1)
10628 interfaces [1] = mono_class_bind_generic_parameters (
10629 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10630 } else if (mono_class_is_ginst (klass)) {
10631 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
10633 mono_class_setup_interfaces (gklass, error);
10634 if (!mono_error_ok (error)) {
10635 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10639 interface_count = gklass->interface_count;
10640 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10641 for (i = 0; i < interface_count; i++) {
10642 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (mono_class_get_generic_class (klass)), error);
10643 if (!mono_error_ok (error)) {
10644 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10649 interface_count = 0;
10653 mono_image_lock (klass->image);
10655 if (!klass->interfaces_inited) {
10656 klass->interface_count = interface_count;
10657 klass->interfaces = interfaces;
10659 mono_memory_barrier ();
10661 klass->interfaces_inited = TRUE;
10664 mono_image_unlock (klass->image);
10668 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10670 MonoClass *klass = field->parent;
10671 MonoImage *image = klass->image;
10672 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10673 int field_idx = field - klass->fields;
10675 mono_error_init (error);
10678 MonoClassField *gfield = >d->fields [field_idx];
10679 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10680 if (!mono_error_ok (error)) {
10681 char *full_name = mono_type_get_full_name (gtd);
10682 mono_class_set_type_load_failure (klass, "Could not load generic type of field '%s:%s' (%d) due to: %s", full_name, gfield->name, field_idx, mono_error_get_message (error));
10683 g_free (full_name);
10686 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10687 if (!mono_error_ok (error)) {
10688 char *full_name = mono_type_get_full_name (klass);
10689 mono_class_set_type_load_failure (klass, "Could not load instantiated type of field '%s:%s' (%d) due to: %s", full_name, field->name, field_idx, mono_error_get_message (error));
10690 g_free (full_name);
10694 guint32 cols [MONO_FIELD_SIZE];
10695 MonoGenericContainer *container = NULL;
10696 int idx = klass->field.first + field_idx;
10698 /*FIXME, in theory we do not lazy load SRE fields*/
10699 g_assert (!image_is_dynamic (image));
10701 if (mono_class_is_gtd (klass)) {
10702 container = mono_class_get_generic_container (klass);
10704 container = mono_class_get_generic_container (gtd);
10705 g_assert (container);
10708 /* klass->field.first and idx points into the fieldptr table */
10709 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10711 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10712 char *full_name = mono_type_get_full_name (klass);
10713 mono_error_set_type_load_class (error, klass, "Could not verify field '%s:%s' signature", full_name, field->name);;
10714 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
10715 g_free (full_name);
10719 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10721 mono_metadata_decode_value (sig, &sig);
10722 /* FIELD signature == 0x06 */
10723 g_assert (*sig == 0x06);
10725 field->type = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10726 if (!field->type) {
10727 char *full_name = mono_type_get_full_name (klass);
10728 mono_class_set_type_load_failure (klass, "Could not load type of field '%s:%s' (%d) due to: %s", full_name, field->name, field_idx, mono_error_get_message (error));
10729 g_free (full_name);
10735 mono_field_resolve_flags (MonoClassField *field)
10737 MonoClass *klass = field->parent;
10738 MonoImage *image = klass->image;
10739 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10740 int field_idx = field - klass->fields;
10744 MonoClassField *gfield = >d->fields [field_idx];
10745 return mono_field_get_flags (gfield);
10747 int idx = klass->field.first + field_idx;
10749 /*FIXME, in theory we do not lazy load SRE fields*/
10750 g_assert (!image_is_dynamic (image));
10752 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10757 * mono_class_get_fields_lazy:
10758 * @klass: the MonoClass to act on
10760 * This routine is an iterator routine for retrieving the fields in a class.
10761 * Only minimal information about fields are loaded. Accessors must be used
10762 * for all MonoClassField returned.
10764 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10765 * iterate over all of the elements. When no more values are
10766 * available, the return value is NULL.
10768 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10771 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10773 MonoClassField* field;
10777 mono_class_setup_basic_field_info (klass);
10778 if (!klass->fields)
10780 /* start from the first */
10781 if (klass->field.count) {
10782 *iter = &klass->fields [0];
10783 return (MonoClassField *)*iter;
10789 field = (MonoClassField *)*iter;
10791 if (field < &klass->fields [klass->field.count]) {
10793 return (MonoClassField *)*iter;
10799 mono_class_full_name (MonoClass *klass)
10801 return mono_type_full_name (&klass->byval_arg);
10804 /* Declare all shared lazy type lookup functions */
10805 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, System.Runtime.InteropServices, SafeHandle)