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);
85 We use gclass recording to allow recursive system f types to be referenced by a parent.
87 Given the following type hierarchy:
89 class TextBox : TextBoxBase<TextBox> {}
90 class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
91 class TextInput<T> : Input<T> where T: TextInput<T> {}
94 The runtime tries to load TextBoxBase<>.
95 To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
96 To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
97 To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
99 At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded
100 at this point, iow, both are registered in the type map and both and a NULL parent. This means
101 that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
103 To fix that what we do is to record all generic instantes created while resolving the parent of
104 any generic type definition and, after resolved, correct the parent field if needed.
107 static int record_gclass_instantiation;
108 static GSList *gclass_recorded_list;
109 typedef gboolean (*gclass_record_func) (MonoClass*, void*);
111 /* This TLS variable points to a GSList of classes which have setup_fields () executing */
112 static MonoNativeTlsKey setup_fields_tls_id;
114 static MonoNativeTlsKey init_pending_tls_id;
119 mono_locks_os_acquire (&classes_mutex, ClassesLock);
123 classes_unlock (void)
125 mono_locks_os_release (&classes_mutex, ClassesLock);
129 * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
132 enable_gclass_recording (void)
134 ++record_gclass_instantiation;
138 * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
141 disable_gclass_recording (gclass_record_func func, void *user_data)
143 GSList **head = &gclass_recorded_list;
145 g_assert (record_gclass_instantiation > 0);
146 --record_gclass_instantiation;
149 GSList *node = *head;
150 if (func ((MonoClass*)node->data, user_data)) {
152 g_slist_free_1 (node);
158 /* We automatically discard all recorded gclasses when disabled. */
159 if (!record_gclass_instantiation && gclass_recorded_list) {
160 g_slist_free (gclass_recorded_list);
161 gclass_recorded_list = NULL;
166 * mono_class_from_typeref:
167 * @image: a MonoImage
168 * @type_token: a TypeRef token
170 * Creates the MonoClass* structure representing the type defined by
171 * the typeref token valid inside @image.
172 * Returns: The MonoClass* representing the typeref token, NULL ifcould
176 mono_class_from_typeref (MonoImage *image, guint32 type_token)
179 MonoClass *klass = mono_class_from_typeref_checked (image, type_token, &error);
180 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
185 * mono_class_from_typeref_checked:
186 * @image: a MonoImage
187 * @type_token: a TypeRef token
188 * @error: error return code, if any.
190 * Creates the MonoClass* structure representing the type defined by
191 * the typeref token valid inside @image.
193 * Returns: The MonoClass* representing the typeref token, NULL if it could
194 * not be loaded with the @error value filled with the information about the
198 mono_class_from_typeref_checked (MonoImage *image, guint32 type_token, MonoError *error)
200 guint32 cols [MONO_TYPEREF_SIZE];
201 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
203 const char *name, *nspace;
204 MonoClass *res = NULL;
207 mono_error_init (error);
209 if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, error))
212 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
214 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
215 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
217 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
218 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
219 case MONO_RESOLUTION_SCOPE_MODULE:
221 LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
222 This is not the observed behavior of existing implementations.
223 The defacto behavior is that it's just a typedef in disguise.
225 /* a typedef in disguise */
226 res = mono_class_from_name_checked (image, nspace, name, error);
229 case MONO_RESOLUTION_SCOPE_MODULEREF:
230 module = mono_image_load_module_checked (image, idx, error);
232 res = mono_class_from_name_checked (module, nspace, name, error);
235 case MONO_RESOLUTION_SCOPE_TYPEREF: {
236 MonoClass *enclosing;
239 if (idx == mono_metadata_token_index (type_token)) {
240 mono_error_set_bad_image (error, image, "Image with self-referencing typeref token %08x.", type_token);
244 enclosing = mono_class_from_typeref_checked (image, MONO_TOKEN_TYPE_REF | idx, error);
245 return_val_if_nok (error, NULL);
247 GList *nested_classes = mono_class_get_nested_classes_property (enclosing);
248 if (enclosing->nested_classes_inited && nested_classes) {
249 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
250 for (tmp = 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 = mono_class_get_field_count (klass);
1284 int i, first_field_idx;
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 first_field_idx = mono_class_get_first_field_idx (klass);
1302 for (i = 0; i < top; i++){
1304 guint32 cols [MONO_FIELD_SIZE];
1305 int idx = first_field_idx + i;
1308 /* first_field_idx and idx points into the fieldptr table */
1309 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1311 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1314 if (!mono_verifier_verify_field_signature (klass->image, cols [MONO_FIELD_SIGNATURE], NULL)) {
1315 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x", cols [MONO_FIELD_SIGNATURE]);
1319 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1320 mono_metadata_decode_value (sig, &sig);
1321 /* FIELD signature == 0x06 */
1323 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig);
1327 ftype = mono_metadata_parse_type_checked (m, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
1331 if (mono_class_is_ginst (klass)) {
1332 //FIXME do we leak here?
1333 ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (klass), error);
1334 if (!mono_error_ok (error))
1336 ftype->attrs = cols [MONO_FIELD_FLAGS];
1341 mono_error_set_type_load_class (error, klass, "Could not find base type");
1348 * Checks for MonoClass::has_failure without resolving all MonoType's into MonoClass'es
1351 mono_type_has_exceptions (MonoType *type)
1353 switch (type->type) {
1354 case MONO_TYPE_CLASS:
1355 case MONO_TYPE_VALUETYPE:
1356 case MONO_TYPE_SZARRAY:
1357 return mono_class_has_failure (type->data.klass);
1358 case MONO_TYPE_ARRAY:
1359 return mono_class_has_failure (type->data.array->eklass);
1360 case MONO_TYPE_GENERICINST:
1361 return mono_class_has_failure (mono_generic_class_get_class (type->data.generic_class));
1368 mono_error_set_for_class_failure (MonoError *oerror, const MonoClass *klass)
1370 g_assert (mono_class_has_failure (klass));
1371 MonoErrorBoxed *box = mono_class_get_exception_data ((MonoClass*)klass);
1372 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->first_field_idx
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 mono_class_set_field_count (klass, mono_class_get_field_count (gtd));
1447 mono_loader_unlock ();
1450 top = mono_class_get_field_count (klass);
1452 fields = (MonoClassField *)mono_class_alloc0 (klass, sizeof (MonoClassField) * top);
1455 * Fetch all the field information.
1457 int first_field_idx = mono_class_has_static_metadata (klass) ? mono_class_get_first_field_idx (klass) : 0;
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 = first_field_idx + i;
1466 /* first_field_idx 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 = mono_class_get_field_count (klass);
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 int first_field_idx = mono_class_has_static_metadata (klass) ? mono_class_get_first_field_idx (klass) : 0;
1591 for (i = 0; i < top; i++) {
1592 int idx = first_field_idx + i;
1593 field = &klass->fields [i];
1596 mono_field_resolve_type (field, &error);
1597 if (!mono_error_ok (&error)) {
1598 /*mono_field_resolve_type already failed class*/
1599 mono_error_cleanup (&error);
1603 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(klass), field->name);
1604 g_assert (field->type);
1607 if (mono_field_is_deleted (field))
1609 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1611 mono_metadata_field_info (m, idx, &uoffset, NULL, NULL);
1612 int offset = uoffset;
1614 if (offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1615 mono_class_set_type_load_failure (klass, "Missing field layout info for %s", field->name);
1618 if (offset < -1) { /*-1 is used to encode special static fields */
1619 mono_class_set_type_load_failure (klass, "Field '%s' has a negative offset %d", field->name, offset);
1622 if (mono_class_is_gtd (klass)) {
1623 mono_class_set_type_load_failure (klass, "Generic class cannot have explicit layout.");
1627 if (mono_type_has_exceptions (field->type)) {
1628 char *class_name = mono_type_get_full_name (klass);
1629 char *type_name = mono_type_full_name (field->type);
1631 mono_class_set_type_load_failure (klass, "");
1632 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1633 g_free (class_name);
1637 /* The def_value of fields is compute lazily during vtable creation */
1640 if (!mono_class_has_failure (klass)) {
1641 mono_loader_lock ();
1642 mono_class_layout_fields (klass, instance_size, packing_size, FALSE);
1643 mono_loader_unlock ();
1646 init_list = g_slist_remove (init_list, klass);
1647 mono_native_tls_set_value (setup_fields_tls_id, init_list);
1651 init_sizes_with_info (MonoClass *klass, MonoCachedClassInfo *cached_info)
1654 klass->instance_size = cached_info->instance_size;
1655 klass->sizes.class_size = cached_info->class_size;
1656 klass->packing_size = cached_info->packing_size;
1657 klass->min_align = cached_info->min_align;
1658 klass->blittable = cached_info->blittable;
1659 klass->has_references = cached_info->has_references;
1660 klass->has_static_refs = cached_info->has_static_refs;
1661 klass->no_special_static_fields = cached_info->no_special_static_fields;
1664 if (!klass->size_inited)
1665 mono_class_setup_fields (klass);
1670 * mono_class_init_sizes:
1672 * Initializes the size related fields of @klass without loading all field data if possible.
1673 * Sets the following fields in @klass:
1675 * - sizes.class_size
1682 * Can fail the class.
1684 * LOCKING: Acquires the loader lock.
1687 mono_class_init_sizes (MonoClass *klass)
1689 MonoCachedClassInfo cached_info;
1690 gboolean has_cached_info;
1692 if (klass->size_inited)
1695 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
1697 init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
1701 * mono_type_get_basic_type_from_generic:
1704 * Returns a closed type corresponding to the possibly open type
1708 mono_type_get_basic_type_from_generic (MonoType *type)
1710 /* When we do generic sharing we let type variables stand for reference/primitive types. */
1711 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) &&
1712 (!type->data.generic_param->gshared_constraint || type->data.generic_param->gshared_constraint->type == MONO_TYPE_OBJECT))
1713 return &mono_defaults.object_class->byval_arg;
1718 class_has_references (MonoClass *klass)
1720 mono_class_init_sizes (klass);
1723 * has_references is not set if this is called recursively, but this is not a problem since this is only used
1724 * during field layout, and instance fields are initialized before static fields, and instance fields can't
1727 return klass->has_references;
1731 type_has_references (MonoClass *klass, MonoType *ftype)
1733 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (klass, ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && class_has_references (mono_class_from_mono_type (ftype)))))
1735 if (!ftype->byref && (ftype->type == MONO_TYPE_VAR || ftype->type == MONO_TYPE_MVAR)) {
1736 MonoGenericParam *gparam = ftype->data.generic_param;
1738 if (gparam->gshared_constraint)
1739 return class_has_references (mono_class_from_mono_type (gparam->gshared_constraint));
1745 * mono_class_layout_fields:
1747 * @base_instance_size: base instance size
1750 * This contains the common code for computing the layout of classes and sizes.
1751 * This should only be called from mono_class_setup_fields () and
1752 * typebuilder_setup_fields ().
1754 * LOCKING: Acquires the loader lock
1757 mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_size, gboolean sre)
1760 const int top = mono_class_get_field_count (klass);
1761 guint32 layout = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK;
1762 guint32 pass, passes, real_size;
1763 gboolean gc_aware_layout = FALSE;
1764 gboolean has_static_fields = FALSE;
1765 gboolean has_references = FALSE;
1766 gboolean has_static_refs = FALSE;
1767 MonoClassField *field;
1769 int instance_size = base_instance_size;
1770 int class_size, min_align;
1772 gboolean *fields_has_references;
1775 * We want to avoid doing complicated work inside locks, so we compute all the required
1776 * information and write it to @klass inside a lock.
1778 if (klass->fields_inited)
1781 if ((packing_size & 0xffffff00) != 0) {
1782 mono_class_set_type_load_failure (klass, "Could not load struct '%s' with packing size %d >= 256", klass->name, packing_size);
1786 if (klass->parent) {
1787 min_align = klass->parent->min_align;
1788 /* we use | since it may have been set already */
1789 has_references = klass->has_references | klass->parent->has_references;
1793 /* We can't really enable 16 bytes alignment until the GC supports it.
1794 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1795 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1796 Bug #506144 is an example of this issue.
1798 if (klass->simd_type)
1803 * When we do generic sharing we need to have layout
1804 * information for open generic classes (either with a generic
1805 * context containing type variables or with a generic
1806 * container), so we don't return in that case anymore.
1809 if (klass->enumtype) {
1810 for (i = 0; i < top; i++) {
1811 field = &klass->fields [i];
1812 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1813 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
1818 if (!mono_class_enum_basetype (klass)) {
1819 mono_class_set_type_load_failure (klass, "The enumeration's base type is invalid.");
1825 * Enable GC aware auto layout: in this mode, reference
1826 * fields are grouped together inside objects, increasing collector
1828 * Requires that all classes whose layout is known to native code be annotated
1829 * with [StructLayout (LayoutKind.Sequential)]
1830 * Value types have gc_aware_layout disabled by default, as per
1831 * what the default is for other runtimes.
1833 /* corlib is missing [StructLayout] directives in many places */
1834 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1835 if (!klass->valuetype)
1836 gc_aware_layout = TRUE;
1839 /* Compute klass->blittable */
1842 blittable = klass->parent->blittable;
1843 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(mono_is_corlib_image (klass->image) && !strcmp (klass->name_space, "System") && !strcmp (klass->name, "ValueType")) && top)
1845 for (i = 0; i < top; i++) {
1846 field = &klass->fields [i];
1848 if (mono_field_is_deleted (field))
1850 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1853 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1856 MonoClass *field_class = mono_class_from_mono_type (field->type);
1858 mono_class_setup_fields (field_class);
1859 if (mono_class_has_failure (field_class)) {
1860 MonoError field_error;
1861 mono_error_init (&field_error);
1862 mono_error_set_for_class_failure (&field_error, field_class);
1863 mono_class_set_type_load_failure (klass, "Could not set up field '%s' due to: %s", field->name, mono_error_get_message (&field_error));
1864 mono_error_cleanup (&field_error);
1868 if (!field_class || !field_class->blittable)
1872 if (klass->enumtype)
1873 blittable = klass->element_class->blittable;
1875 if (mono_class_has_failure (klass))
1877 if (klass == mono_defaults.string_class)
1880 /* Compute klass->has_references */
1882 * Process non-static fields first, since static fields might recursively
1883 * refer to the class itself.
1885 for (i = 0; i < top; i++) {
1888 field = &klass->fields [i];
1890 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1891 ftype = mono_type_get_underlying_type (field->type);
1892 ftype = mono_type_get_basic_type_from_generic (ftype);
1893 if (type_has_references (klass, ftype))
1894 has_references = TRUE;
1899 * Compute field layout and total size (not considering static fields)
1901 field_offsets = g_new0 (int, top);
1902 fields_has_references = g_new0 (gboolean, top);
1903 int first_field_idx = mono_class_has_static_metadata (klass) ? mono_class_get_first_field_idx (klass) : 0;
1905 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1906 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1907 if (gc_aware_layout)
1912 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1915 if (klass->parent) {
1916 mono_class_setup_fields (klass->parent);
1917 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Cannot initialize parent class"))
1919 real_size = klass->parent->instance_size;
1921 real_size = sizeof (MonoObject);
1924 for (pass = 0; pass < passes; ++pass) {
1925 for (i = 0; i < top; i++){
1930 field = &klass->fields [i];
1932 if (mono_field_is_deleted (field))
1934 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1937 ftype = mono_type_get_underlying_type (field->type);
1938 ftype = mono_type_get_basic_type_from_generic (ftype);
1939 if (gc_aware_layout) {
1940 fields_has_references [i] = type_has_references (klass, ftype);
1941 if (fields_has_references [i]) {
1950 if ((top == 1) && (instance_size == sizeof (MonoObject)) &&
1951 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1952 /* This field is a hack inserted by MCS to empty structures */
1956 size = mono_type_size (field->type, &align);
1958 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1959 align = packing_size ? MIN (packing_size, align): align;
1960 /* if the field has managed references, we need to force-align it
1963 if (type_has_references (klass, ftype))
1964 align = MAX (align, sizeof (gpointer));
1966 min_align = MAX (align, min_align);
1967 field_offsets [i] = real_size;
1969 field_offsets [i] += align - 1;
1970 field_offsets [i] &= ~(align - 1);
1972 /*TypeBuilders produce all sort of weird things*/
1973 g_assert (image_is_dynamic (klass->image) || field_offsets [i] > 0);
1974 real_size = field_offsets [i] + size;
1977 /* Make SIMD types as big as a SIMD register since they can be stored into using simd stores */
1978 if (klass->simd_type)
1979 real_size = MAX (real_size, sizeof (MonoObject) + 16);
1980 instance_size = MAX (real_size, instance_size);
1982 if (instance_size & (min_align - 1)) {
1983 instance_size += min_align - 1;
1984 instance_size &= ~(min_align - 1);
1988 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
1992 for (i = 0; i < top; i++) {
1997 field = &klass->fields [i];
2000 * There must be info about all the fields in a type if it
2001 * uses explicit layout.
2003 if (mono_field_is_deleted (field))
2005 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2008 size = mono_type_size (field->type, &align);
2009 align = packing_size ? MIN (packing_size, align): align;
2010 min_align = MAX (align, min_align);
2013 /* Already set by typebuilder_setup_fields () */
2014 field_offsets [i] = field->offset + sizeof (MonoObject);
2016 int idx = first_field_idx + i;
2018 mono_metadata_field_info (klass->image, idx, &offset, NULL, NULL);
2019 field_offsets [i] = offset + sizeof (MonoObject);
2021 ftype = mono_type_get_underlying_type (field->type);
2022 ftype = mono_type_get_basic_type_from_generic (ftype);
2023 if (type_has_references (klass, ftype)) {
2024 if (field_offsets [i] % sizeof (gpointer)) {
2025 mono_class_set_type_load_failure (klass, "Reference typed field '%s' has explicit offset that is not pointer-size aligned.", field->name);
2032 real_size = MAX (real_size, size + field_offsets [i]);
2035 if (klass->has_references) {
2036 ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
2038 /* Check for overlapping reference and non-reference fields */
2039 for (i = 0; i < top; i++) {
2042 field = &klass->fields [i];
2044 if (mono_field_is_deleted (field))
2046 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2048 ftype = mono_type_get_underlying_type (field->type);
2049 if (MONO_TYPE_IS_REFERENCE (ftype))
2050 ref_bitmap [field_offsets [i] / sizeof (gpointer)] = 1;
2052 for (i = 0; i < top; i++) {
2053 field = &klass->fields [i];
2055 if (mono_field_is_deleted (field))
2057 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2060 // FIXME: Too much code does this
2062 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field_offsets [i] / sizeof (gpointer)]) {
2063 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]);
2067 g_free (ref_bitmap);
2070 instance_size = MAX (real_size, instance_size);
2071 if (instance_size & (min_align - 1)) {
2072 instance_size += min_align - 1;
2073 instance_size &= ~(min_align - 1);
2079 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2081 * This leads to all kinds of problems with nested structs, so only
2082 * enable it when a MONO_DEBUG property is set.
2084 * For small structs, set min_align to at least the struct size to improve
2085 * performance, and since the JIT memset/memcpy code assumes this and generates
2086 * unaligned accesses otherwise. See #78990 for a testcase.
2088 if (mono_align_small_structs && top) {
2089 if (instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2090 min_align = MAX (min_align, instance_size - sizeof (MonoObject));
2094 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR)
2095 instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
2096 else if (klass->byval_arg.type == MONO_TYPE_PTR)
2097 instance_size = sizeof (MonoObject) + sizeof (gpointer);
2099 /* Publish the data */
2100 mono_loader_lock ();
2101 if (klass->instance_size && !klass->image->dynamic) {
2102 /* Might be already set using cached info */
2103 if (klass->instance_size != instance_size) {
2104 /* Emit info to help debugging */
2105 g_print ("%s\n", mono_class_full_name (klass));
2106 g_print ("%d %d %d %d\n", klass->instance_size, instance_size, klass->blittable, blittable);
2107 g_print ("%d %d %d %d\n", klass->has_references, has_references, klass->packing_size, packing_size);
2108 g_print ("%d %d\n", klass->min_align, min_align);
2109 for (i = 0; i < top; ++i) {
2110 field = &klass->fields [i];
2111 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
2112 printf (" %s %d %d %d\n", klass->fields [i].name, klass->fields [i].offset, field_offsets [i], fields_has_references [i]);
2115 g_assert (klass->instance_size == instance_size);
2117 klass->instance_size = instance_size;
2119 klass->blittable = blittable;
2120 klass->has_references = has_references;
2121 klass->packing_size = packing_size;
2122 klass->min_align = min_align;
2123 for (i = 0; i < top; ++i) {
2124 field = &klass->fields [i];
2125 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
2126 klass->fields [i].offset = field_offsets [i];
2129 mono_memory_barrier ();
2130 klass->size_inited = 1;
2131 mono_loader_unlock ();
2134 * Compute static field layout and size
2135 * Static fields can reference the class itself, so this has to be
2136 * done after instance_size etc. are initialized.
2139 for (i = 0; i < top; i++) {
2143 field = &klass->fields [i];
2145 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2147 if (mono_field_is_deleted (field))
2150 if (mono_type_has_exceptions (field->type)) {
2151 mono_class_set_type_load_failure (klass, "Field '%s' has an invalid type.", field->name);
2155 has_static_fields = TRUE;
2157 size = mono_type_size (field->type, &align);
2158 field_offsets [i] = class_size;
2159 /*align is always non-zero here*/
2160 field_offsets [i] += align - 1;
2161 field_offsets [i] &= ~(align - 1);
2162 class_size = field_offsets [i] + size;
2165 if (has_static_fields && class_size == 0)
2166 /* Simplify code which depends on class_size != 0 if the class has static fields */
2169 /* Compute klass->has_static_refs */
2170 has_static_refs = FALSE;
2171 for (i = 0; i < top; i++) {
2174 field = &klass->fields [i];
2176 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
2177 ftype = mono_type_get_underlying_type (field->type);
2178 ftype = mono_type_get_basic_type_from_generic (ftype);
2179 if (type_has_references (klass, ftype))
2180 has_static_refs = TRUE;
2184 /*valuetypes can't be neither bigger than 1Mb or empty. */
2185 if (klass->valuetype && (klass->instance_size <= 0 || klass->instance_size > (0x100000 + sizeof (MonoObject))))
2186 mono_class_set_type_load_failure (klass, "Value type instance size (%d) cannot be zero, negative, or bigger than 1Mb", klass->instance_size);
2188 /* Publish the data */
2189 mono_loader_lock ();
2191 klass->sizes.class_size = class_size;
2192 klass->has_static_refs = has_static_refs;
2193 for (i = 0; i < top; ++i) {
2194 field = &klass->fields [i];
2196 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2197 field->offset = field_offsets [i];
2200 mono_memory_barrier ();
2201 klass->fields_inited = 1;
2202 mono_loader_unlock ();
2204 g_free (field_offsets);
2205 g_free (fields_has_references);
2209 create_array_method (MonoClass *klass, const char *name, MonoMethodSignature *sig)
2213 method = (MonoMethod *) mono_image_alloc0 (klass->image, sizeof (MonoMethodPInvoke));
2214 method->klass = klass;
2215 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2216 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2217 method->signature = sig;
2218 method->name = name;
2221 if (name [0] == '.') {
2222 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2224 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2230 * mono_class_setup_methods:
2233 * Initializes the 'methods' array in CLASS.
2234 * Calling this method should be avoided if possible since it allocates a lot
2235 * of long-living MonoMethod structures.
2236 * Methods belonging to an interface are assigned a sequential slot starting
2239 * On failure this function sets klass->has_failure and stores a MonoErrorBoxed with details
2242 mono_class_setup_methods (MonoClass *klass)
2245 MonoMethod **methods;
2250 if (mono_class_is_ginst (klass)) {
2252 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2254 mono_class_init (gklass);
2255 if (!mono_class_has_failure (gklass))
2256 mono_class_setup_methods (gklass);
2257 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2260 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2261 count = mono_class_get_method_count (gklass);
2262 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * (count + 1));
2264 for (i = 0; i < count; i++) {
2265 methods [i] = mono_class_inflate_generic_method_full_checked (
2266 gklass->methods [i], klass, mono_class_get_context (klass), &error);
2267 if (!mono_error_ok (&error)) {
2268 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2269 mono_class_set_type_load_failure (klass, "Could not inflate method %s due to %s", method, mono_error_get_message (&error));
2272 mono_error_cleanup (&error);
2276 } else if (klass->rank) {
2278 MonoMethod *amethod;
2279 MonoMethodSignature *sig;
2280 int count_generic = 0, first_generic = 0;
2282 gboolean jagged_ctor = FALSE;
2284 count = 3 + (klass->rank > 1? 2: 1);
2286 mono_class_setup_interfaces (klass, &error);
2287 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2289 if (klass->rank == 1 && klass->element_class->rank) {
2294 if (klass->interface_count) {
2295 count_generic = generic_array_methods (klass);
2296 first_generic = count;
2297 count += klass->interface_count * count_generic;
2300 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * count);
2302 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2303 sig->ret = &mono_defaults.void_class->byval_arg;
2304 sig->pinvoke = TRUE;
2305 sig->hasthis = TRUE;
2306 for (i = 0; i < klass->rank; ++i)
2307 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2309 amethod = create_array_method (klass, ".ctor", sig);
2310 methods [method_num++] = amethod;
2311 if (klass->rank > 1) {
2312 sig = mono_metadata_signature_alloc (klass->image, klass->rank * 2);
2313 sig->ret = &mono_defaults.void_class->byval_arg;
2314 sig->pinvoke = TRUE;
2315 sig->hasthis = TRUE;
2316 for (i = 0; i < klass->rank * 2; ++i)
2317 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2319 amethod = create_array_method (klass, ".ctor", sig);
2320 methods [method_num++] = amethod;
2324 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2325 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2326 sig->ret = &mono_defaults.void_class->byval_arg;
2327 sig->pinvoke = TRUE;
2328 sig->hasthis = TRUE;
2329 for (i = 0; i < klass->rank + 1; ++i)
2330 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2331 amethod = create_array_method (klass, ".ctor", sig);
2332 methods [method_num++] = amethod;
2335 /* element Get (idx11, [idx2, ...]) */
2336 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2337 sig->ret = &klass->element_class->byval_arg;
2338 sig->pinvoke = TRUE;
2339 sig->hasthis = TRUE;
2340 for (i = 0; i < klass->rank; ++i)
2341 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2342 amethod = create_array_method (klass, "Get", sig);
2343 methods [method_num++] = amethod;
2344 /* element& Address (idx11, [idx2, ...]) */
2345 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2346 sig->ret = &klass->element_class->this_arg;
2347 sig->pinvoke = TRUE;
2348 sig->hasthis = TRUE;
2349 for (i = 0; i < klass->rank; ++i)
2350 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2351 amethod = create_array_method (klass, "Address", sig);
2352 methods [method_num++] = amethod;
2353 /* void Set (idx11, [idx2, ...], element) */
2354 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2355 sig->ret = &mono_defaults.void_class->byval_arg;
2356 sig->pinvoke = TRUE;
2357 sig->hasthis = TRUE;
2358 for (i = 0; i < klass->rank; ++i)
2359 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2360 sig->params [i] = &klass->element_class->byval_arg;
2361 amethod = create_array_method (klass, "Set", sig);
2362 methods [method_num++] = amethod;
2364 for (i = 0; i < klass->interface_count; i++)
2365 setup_generic_array_ifaces (klass, klass->interfaces [i], methods, first_generic + i * count_generic);
2366 } else if (mono_class_has_static_metadata (klass)) {
2368 int first_idx = mono_class_get_first_method_idx (klass);
2370 count = mono_class_get_method_count (klass);
2371 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * count);
2372 for (i = 0; i < count; ++i) {
2373 int idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_METHOD, first_idx + i + 1);
2374 methods [i] = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | idx, klass, NULL, &error);
2376 mono_class_set_type_load_failure (klass, "Could not load method %d due to %s", i, mono_error_get_message (&error));
2377 mono_error_cleanup (&error);
2381 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * 1);
2385 if (MONO_CLASS_IS_INTERFACE (klass)) {
2387 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2388 for (i = 0; i < count; ++i) {
2389 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2390 methods [i]->slot = slot++;
2394 mono_image_lock (klass->image);
2396 if (!klass->methods) {
2397 mono_class_set_method_count (klass, count);
2399 /* Needed because of the double-checking locking pattern */
2400 mono_memory_barrier ();
2402 klass->methods = methods;
2405 mono_image_unlock (klass->image);
2409 * mono_class_get_method_by_index:
2411 * Returns klass->methods [index], initializing klass->methods if neccesary.
2413 * LOCKING: Acquires the loader lock.
2416 mono_class_get_method_by_index (MonoClass *klass, int index)
2420 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
2421 /* Avoid calling setup_methods () if possible */
2422 if (gklass && !klass->methods) {
2425 m = mono_class_inflate_generic_method_full_checked (
2426 gklass->container_class->methods [index], klass, mono_class_get_context (klass), &error);
2427 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2429 * If setup_methods () is called later for this class, no duplicates are created,
2430 * since inflate_generic_method guarantees that only one instance of a method
2431 * is created for each context.
2434 mono_class_setup_methods (klass);
2435 g_assert (m == klass->methods [index]);
2439 mono_class_setup_methods (klass);
2440 if (mono_class_has_failure (klass)) /*FIXME do proper error handling*/
2442 g_assert (index >= 0 && index < mono_class_get_method_count (klass));
2443 return klass->methods [index];
2448 * mono_class_get_inflated_method:
2450 * Given an inflated class CLASS and a method METHOD which should be a method of
2451 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2454 mono_class_get_inflated_method (MonoClass *klass, MonoMethod *method)
2456 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2459 g_assert (method->klass == gklass);
2461 mono_class_setup_methods (gklass);
2462 g_assert (!mono_class_has_failure (gklass)); /*FIXME do proper error handling*/
2464 mcount = mono_class_get_method_count (gklass);
2465 for (i = 0; i < mcount; ++i) {
2466 if (gklass->methods [i] == method) {
2467 if (klass->methods) {
2468 return klass->methods [i];
2471 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], klass, mono_class_get_context (klass), &error);
2472 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2482 * mono_class_get_vtable_entry:
2484 * Returns klass->vtable [offset], computing it if neccesary. Returns NULL on failure.
2485 * LOCKING: Acquires the loader lock.
2488 mono_class_get_vtable_entry (MonoClass *klass, int offset)
2492 if (klass->rank == 1) {
2494 * szarrays do not overwrite any methods of Array, so we can avoid
2495 * initializing their vtables in some cases.
2497 mono_class_setup_vtable (klass->parent);
2498 if (offset < klass->parent->vtable_size)
2499 return klass->parent->vtable [offset];
2502 if (mono_class_is_ginst (klass)) {
2504 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2505 mono_class_setup_vtable (gklass);
2506 m = gklass->vtable [offset];
2508 m = mono_class_inflate_generic_method_full_checked (m, klass, mono_class_get_context (klass), &error);
2509 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2511 mono_class_setup_vtable (klass);
2512 if (mono_class_has_failure (klass))
2514 m = klass->vtable [offset];
2521 * mono_class_get_vtable_size:
2523 * Return the vtable size for KLASS.
2526 mono_class_get_vtable_size (MonoClass *klass)
2528 mono_class_setup_vtable (klass);
2530 return klass->vtable_size;
2534 * mono_class_setup_properties:
2536 * Initialize klass->ext.property and klass->ext.properties.
2538 * This method can fail the class.
2541 mono_class_setup_properties (MonoClass *klass)
2543 guint startm, endm, i, j;
2544 guint32 cols [MONO_PROPERTY_SIZE];
2545 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2546 MonoProperty *properties;
2549 MonoClassPropertyInfo *info;
2551 info = mono_class_get_property_info (klass);
2555 if (mono_class_is_ginst (klass)) {
2556 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2558 mono_class_init (gklass);
2559 mono_class_setup_properties (gklass);
2560 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2563 MonoClassPropertyInfo *ginfo = mono_class_get_property_info (gklass);
2564 properties = mono_class_new0 (klass, MonoProperty, ginfo->count + 1);
2566 for (i = 0; i < ginfo->count; i++) {
2568 MonoProperty *prop = &properties [i];
2570 *prop = ginfo->properties [i];
2573 prop->get = mono_class_inflate_generic_method_full_checked (
2574 prop->get, klass, mono_class_get_context (klass), &error);
2576 prop->set = mono_class_inflate_generic_method_full_checked (
2577 prop->set, klass, mono_class_get_context (klass), &error);
2579 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2580 prop->parent = klass;
2583 first = ginfo->first;
2584 count = ginfo->count;
2586 first = mono_metadata_properties_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2587 count = last - first;
2590 mono_class_setup_methods (klass);
2591 if (mono_class_has_failure (klass))
2595 properties = (MonoProperty *)mono_class_alloc0 (klass, sizeof (MonoProperty) * count);
2596 for (i = first; i < last; ++i) {
2597 mono_metadata_decode_table_row (klass->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2598 properties [i - first].parent = klass;
2599 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2600 properties [i - first].name = mono_metadata_string_heap (klass->image, cols [MONO_PROPERTY_NAME]);
2602 startm = mono_metadata_methods_from_property (klass->image, i, &endm);
2603 int first_idx = mono_class_get_first_method_idx (klass);
2604 for (j = startm; j < endm; ++j) {
2607 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2609 if (klass->image->uncompressed_metadata) {
2611 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2612 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2613 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2615 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - first_idx];
2618 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2619 case METHOD_SEMANTIC_SETTER:
2620 properties [i - first].set = method;
2622 case METHOD_SEMANTIC_GETTER:
2623 properties [i - first].get = method;
2632 info = mono_class_alloc0 (klass, sizeof (MonoClassPropertyInfo));
2633 info->first = first;
2634 info->count = count;
2635 info->properties = properties;
2636 mono_memory_barrier ();
2638 /* This might leak 'info' which was allocated from the image mempool */
2639 mono_class_set_property_info (klass, info);
2643 inflate_method_listz (MonoMethod **methods, MonoClass *klass, MonoGenericContext *context)
2645 MonoMethod **om, **retval;
2648 for (om = methods, count = 0; *om; ++om, ++count)
2651 retval = g_new0 (MonoMethod*, count + 1);
2653 for (om = methods, count = 0; *om; ++om, ++count) {
2655 retval [count] = mono_class_inflate_generic_method_full_checked (*om, klass, context, &error);
2656 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2662 /*This method can fail the class.*/
2664 mono_class_setup_events (MonoClass *klass)
2667 guint startm, endm, i, j;
2668 guint32 cols [MONO_EVENT_SIZE];
2669 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2673 MonoClassEventInfo *info = mono_class_get_event_info (klass);
2677 if (mono_class_is_ginst (klass)) {
2678 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2679 MonoGenericContext *context = NULL;
2681 mono_class_setup_events (gklass);
2682 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2685 MonoClassEventInfo *ginfo = mono_class_get_event_info (gklass);
2686 first = ginfo->first;
2687 count = ginfo->count;
2689 events = mono_class_new0 (klass, MonoEvent, count);
2692 context = mono_class_get_context (klass);
2694 for (i = 0; i < count; i++) {
2696 MonoEvent *event = &events [i];
2697 MonoEvent *gevent = &ginfo->events [i];
2699 mono_error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2701 event->parent = klass;
2702 event->name = gevent->name;
2703 event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, klass, context, &error) : NULL;
2704 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2705 event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, klass, context, &error) : NULL;
2706 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2707 event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, klass, context, &error) : NULL;
2708 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2710 #ifndef MONO_SMALL_CONFIG
2711 event->other = gevent->other ? inflate_method_listz (gevent->other, klass, context) : NULL;
2713 event->attrs = gevent->attrs;
2716 first = mono_metadata_events_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2717 count = last - first;
2720 mono_class_setup_methods (klass);
2721 if (mono_class_has_failure (klass)) {
2726 events = (MonoEvent *)mono_class_alloc0 (klass, sizeof (MonoEvent) * count);
2727 for (i = first; i < last; ++i) {
2728 MonoEvent *event = &events [i - first];
2730 mono_metadata_decode_table_row (klass->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2731 event->parent = klass;
2732 event->attrs = cols [MONO_EVENT_FLAGS];
2733 event->name = mono_metadata_string_heap (klass->image, cols [MONO_EVENT_NAME]);
2735 startm = mono_metadata_methods_from_event (klass->image, i, &endm);
2736 int first_idx = mono_class_get_first_method_idx (klass);
2737 for (j = startm; j < endm; ++j) {
2740 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2742 if (klass->image->uncompressed_metadata) {
2744 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2745 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2746 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2748 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - first_idx];
2751 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2752 case METHOD_SEMANTIC_ADD_ON:
2753 event->add = method;
2755 case METHOD_SEMANTIC_REMOVE_ON:
2756 event->remove = method;
2758 case METHOD_SEMANTIC_FIRE:
2759 event->raise = method;
2761 case METHOD_SEMANTIC_OTHER: {
2762 #ifndef MONO_SMALL_CONFIG
2765 if (event->other == NULL) {
2766 event->other = g_new0 (MonoMethod*, 2);
2768 while (event->other [n])
2770 event->other = (MonoMethod **)g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2772 event->other [n] = method;
2773 /* NULL terminated */
2774 event->other [n + 1] = NULL;
2785 info = mono_class_alloc0 (klass, sizeof (MonoClassEventInfo));
2786 info->events = events;
2787 info->first = first;
2788 info->count = count;
2790 mono_memory_barrier ();
2792 mono_class_set_event_info (klass, info);
2796 * Global pool of interface IDs, represented as a bitset.
2797 * LOCKING: Protected by the classes lock.
2799 static MonoBitSet *global_interface_bitset = NULL;
2802 * mono_unload_interface_ids:
2803 * @bitset: bit set of interface IDs
2805 * When an image is unloaded, the interface IDs associated with
2806 * the image are put back in the global pool of IDs so the numbers
2810 mono_unload_interface_ids (MonoBitSet *bitset)
2813 mono_bitset_sub (global_interface_bitset, bitset);
2818 mono_unload_interface_id (MonoClass *klass)
2820 if (global_interface_bitset && klass->interface_id) {
2822 mono_bitset_clear (global_interface_bitset, klass->interface_id);
2828 * mono_get_unique_iid:
2831 * Assign a unique integer ID to the interface represented by @class.
2832 * The ID will positive and as small as possible.
2833 * LOCKING: Acquires the classes lock.
2834 * Returns: The new ID.
2837 mono_get_unique_iid (MonoClass *klass)
2841 g_assert (MONO_CLASS_IS_INTERFACE (klass));
2845 if (!global_interface_bitset) {
2846 global_interface_bitset = mono_bitset_new (128, 0);
2849 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2851 int old_size = mono_bitset_size (global_interface_bitset);
2852 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2853 mono_bitset_free (global_interface_bitset);
2854 global_interface_bitset = new_set;
2857 mono_bitset_set (global_interface_bitset, iid);
2858 /* set the bit also in the per-image set */
2859 if (!mono_class_is_ginst (klass)) {
2860 if (klass->image->interface_bitset) {
2861 if (iid >= mono_bitset_size (klass->image->interface_bitset)) {
2862 MonoBitSet *new_set = mono_bitset_clone (klass->image->interface_bitset, iid + 1);
2863 mono_bitset_free (klass->image->interface_bitset);
2864 klass->image->interface_bitset = new_set;
2867 klass->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2869 mono_bitset_set (klass->image->interface_bitset, iid);
2874 #ifndef MONO_SMALL_CONFIG
2875 if (mono_print_vtable) {
2877 char *type_name = mono_type_full_name (&klass->byval_arg);
2878 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
2879 if (gklass && !gklass->context.class_inst->is_open) {
2880 generic_id = gklass->context.class_inst->id;
2881 g_assert (generic_id != 0);
2885 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, klass->image->name, type_name, generic_id);
2890 /* I've confirmed iids safe past 16 bits, however bitset code uses a signed int while testing.
2891 * Once this changes, it should be safe for us to allow 2^32-1 interfaces, until then 2^31-2 is the max. */
2892 g_assert (iid < INT_MAX);
2897 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, GHashTable **ifaces, MonoError *error)
2902 mono_class_setup_interfaces (klass, error);
2903 return_if_nok (error);
2905 for (i = 0; i < klass->interface_count; i++) {
2906 ic = klass->interfaces [i];
2909 *res = g_ptr_array_new ();
2910 if (*ifaces == NULL)
2911 *ifaces = g_hash_table_new (NULL, NULL);
2912 if (g_hash_table_lookup (*ifaces, ic))
2914 g_ptr_array_add (*res, ic);
2915 g_hash_table_insert (*ifaces, ic, ic);
2916 mono_class_init (ic);
2917 if (mono_class_has_failure (ic)) {
2918 mono_error_set_type_load_class (error, ic, "Error Loading class");
2922 collect_implemented_interfaces_aux (ic, res, ifaces, error);
2923 return_if_nok (error);
2928 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2930 GPtrArray *res = NULL;
2931 GHashTable *ifaces = NULL;
2933 collect_implemented_interfaces_aux (klass, &res, &ifaces, error);
2935 g_hash_table_destroy (ifaces);
2936 if (!mono_error_ok (error)) {
2938 g_ptr_array_free (res, TRUE);
2945 compare_interface_ids (const void *p_key, const void *p_element)
2947 const MonoClass *key = (const MonoClass *)p_key;
2948 const MonoClass *element = *(const MonoClass **)p_element;
2950 return (key->interface_id - element->interface_id);
2953 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2955 mono_class_interface_offset (MonoClass *klass, MonoClass *itf)
2957 MonoClass **result = (MonoClass **)mono_binary_search (
2959 klass->interfaces_packed,
2960 klass->interface_offsets_count,
2961 sizeof (MonoClass *),
2962 compare_interface_ids);
2964 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2971 * mono_class_interface_offset_with_variance:
2973 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2974 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2976 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2978 * FIXME figure out MS disambiguation rules and fix this function.
2981 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match)
2983 int i = mono_class_interface_offset (klass, itf);
2984 *non_exact_match = FALSE;
2988 if (itf->is_array_special_interface && klass->rank < 2) {
2989 MonoClass *gtd = mono_class_get_generic_type_definition (itf);
2991 for (i = 0; i < klass->interface_offsets_count; i++) {
2992 // printf ("\t%s\n", mono_type_get_full_name (klass->interfaces_packed [i]));
2993 if (mono_class_get_generic_type_definition (klass->interfaces_packed [i]) == gtd) {
2994 *non_exact_match = TRUE;
2995 return klass->interface_offsets_packed [i];
3000 if (!mono_class_has_variant_generic_params (itf))
3003 for (i = 0; i < klass->interface_offsets_count; i++) {
3004 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
3005 *non_exact_match = TRUE;
3006 return klass->interface_offsets_packed [i];
3014 print_implemented_interfaces (MonoClass *klass)
3018 GPtrArray *ifaces = NULL;
3020 int ancestor_level = 0;
3022 name = mono_type_get_full_name (klass);
3023 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
3026 for (i = 0; i < klass->interface_offsets_count; i++)
3027 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3028 klass->interfaces_packed [i]->interface_id,
3029 klass->interface_offsets_packed [i],
3030 mono_class_get_method_count (klass->interfaces_packed [i]),
3031 klass->interfaces_packed [i]->name_space,
3032 klass->interfaces_packed [i]->name );
3033 printf ("Interface flags: ");
3034 for (i = 0; i <= klass->max_interface_id; i++)
3035 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
3036 printf ("(%d,T)", i);
3038 printf ("(%d,F)", i);
3040 printf ("Dump interface flags:");
3041 #ifdef COMPRESSED_INTERFACE_BITMAP
3043 const uint8_t* p = klass->interface_bitmap;
3044 i = klass->max_interface_id;
3046 printf (" %d x 00 %02X", p [0], p [1]);
3052 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
3053 printf (" %02X", klass->interface_bitmap [i]);
3056 while (klass != NULL) {
3057 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
3058 ifaces = mono_class_get_implemented_interfaces (klass, &error);
3059 if (!mono_error_ok (&error)) {
3060 printf (" Type failed due to %s\n", mono_error_get_message (&error));
3061 mono_error_cleanup (&error);
3062 } else if (ifaces) {
3063 for (i = 0; i < ifaces->len; i++) {
3064 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3065 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
3066 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3068 mono_class_interface_offset (klass, ic),
3069 mono_class_get_method_count (ic),
3073 g_ptr_array_free (ifaces, TRUE);
3076 klass = klass->parent;
3081 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
3084 args [0] = &arg0->byval_arg;
3086 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
3090 array_class_get_if_rank (MonoClass *klass, guint rank)
3092 return rank ? mono_array_class_get (klass, rank) : klass;
3096 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
3098 valuetype_types [0] = eclass;
3099 if (eclass == mono_defaults.int16_class)
3100 valuetype_types [1] = mono_defaults.uint16_class;
3101 else if (eclass == mono_defaults.uint16_class)
3102 valuetype_types [1] = mono_defaults.int16_class;
3103 else if (eclass == mono_defaults.int32_class)
3104 valuetype_types [1] = mono_defaults.uint32_class;
3105 else if (eclass == mono_defaults.uint32_class)
3106 valuetype_types [1] = mono_defaults.int32_class;
3107 else if (eclass == mono_defaults.int64_class)
3108 valuetype_types [1] = mono_defaults.uint64_class;
3109 else if (eclass == mono_defaults.uint64_class)
3110 valuetype_types [1] = mono_defaults.int64_class;
3111 else if (eclass == mono_defaults.byte_class)
3112 valuetype_types [1] = mono_defaults.sbyte_class;
3113 else if (eclass == mono_defaults.sbyte_class)
3114 valuetype_types [1] = mono_defaults.byte_class;
3115 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
3116 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
3119 static GENERATE_GET_CLASS_WITH_CACHE (generic_icollection, System.Collections.Generic, ICollection`1)
3120 static GENERATE_GET_CLASS_WITH_CACHE (generic_ienumerable, System.Collections.Generic, IEnumerable`1)
3121 static GENERATE_GET_CLASS_WITH_CACHE (generic_ienumerator, System.Collections.Generic, IEnumerator`1)
3122 static GENERATE_GET_CLASS_WITH_CACHE (generic_ireadonlylist, System.Collections.Generic, IReadOnlyList`1)
3123 static GENERATE_GET_CLASS_WITH_CACHE (generic_ireadonlycollection, System.Collections.Generic, IReadOnlyCollection`1)
3126 find_array_interface (MonoClass *klass, const char *name)
3129 for (i = 0; i < klass->interface_count; ++i) {
3130 if (strcmp (klass->interfaces [i]->name, name) == 0)
3137 * Return the number of virtual methods.
3138 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3139 * Return -1 on failure.
3140 * FIXME It would be nice if this information could be cached somewhere.
3143 count_virtual_methods (MonoClass *klass)
3145 int i, mcount, vcount = 0;
3147 klass = mono_class_get_generic_type_definition (klass); /*We can find this information by looking at the GTD*/
3149 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
3150 mono_class_setup_methods (klass);
3151 if (mono_class_has_failure (klass))
3154 mcount = mono_class_get_method_count (klass);
3155 for (i = 0; i < mcount; ++i) {
3156 flags = klass->methods [i]->flags;
3157 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3161 int first_idx = mono_class_get_first_method_idx (klass);
3162 mcount = mono_class_get_method_count (klass);
3163 for (i = 0; i < mcount; ++i) {
3164 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
3166 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3174 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3182 m = (l + num_ifaces) / 2;
3183 if (interfaces_full [m] == ic)
3185 if (l == num_ifaces)
3187 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3196 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3198 int i = find_interface (num_ifaces, interfaces_full, ic);
3200 return interface_offsets_full [i];
3205 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3207 int i = find_interface (num_ifaces, interfaces_full, ic);
3211 interface_offsets_full [i] = offset;
3214 for (i = 0; i < num_ifaces; ++i) {
3215 if (interfaces_full [i]) {
3217 if (interfaces_full [i]->interface_id < ic->interface_id)
3220 while (end < num_ifaces && interfaces_full [end]) end++;
3221 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3222 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3224 interfaces_full [i] = ic;
3225 interface_offsets_full [i] = offset;
3231 #ifdef COMPRESSED_INTERFACE_BITMAP
3234 * Compressed interface bitmap design.
3236 * Interface bitmaps take a large amount of memory, because their size is
3237 * linear with the maximum interface id assigned in the process (each interface
3238 * is assigned a unique id as it is loaded). The number of interface classes
3239 * is high because of the many implicit interfaces implemented by arrays (we'll
3240 * need to lazy-load them in the future).
3241 * Most classes implement a very small number of interfaces, so the bitmap is
3242 * sparse. This bitmap needs to be checked by interface casts, so access to the
3243 * needed bit must be fast and doable with few jit instructions.
3245 * The current compression format is as follows:
3246 * *) it is a sequence of one or more two-byte elements
3247 * *) the first byte in the element is the count of empty bitmap bytes
3248 * at the current bitmap position
3249 * *) the second byte in the element is an actual bitmap byte at the current
3252 * As an example, the following compressed bitmap bytes:
3253 * 0x07 0x01 0x00 0x7
3254 * correspond to the following bitmap:
3255 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3257 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3258 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3259 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3263 * mono_compress_bitmap:
3264 * @dest: destination buffer
3265 * @bitmap: bitmap buffer
3266 * @size: size of @bitmap in bytes
3268 * This is a mono internal function.
3269 * The @bitmap data is compressed into a format that is small but
3270 * still searchable in few instructions by the JIT and runtime.
3271 * The compressed data is stored in the buffer pointed to by the
3272 * @dest array. Passing a #NULL value for @dest allows to just compute
3273 * the size of the buffer.
3274 * This compression algorithm assumes the bits set in the bitmap are
3275 * few and far between, like in interface bitmaps.
3276 * Returns: The size of the compressed bitmap in bytes.
3279 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3283 const uint8_t *end = bitmap + size;
3284 while (bitmap < end) {
3285 if (*bitmap || numz == 255) {
3309 * mono_class_interface_match:
3310 * @bitmap: a compressed bitmap buffer
3311 * @id: the index to check in the bitmap
3313 * This is a mono internal function.
3314 * Checks if a bit is set in a compressed interface bitmap. @id must
3315 * be already checked for being smaller than the maximum id encoded in the
3318 * Returns: A non-zero value if bit @id is set in the bitmap @bitmap,
3322 mono_class_interface_match (const uint8_t *bitmap, int id)
3325 id -= bitmap [0] * 8;
3329 return bitmap [1] & (1 << id);
3338 * Return -1 on failure and set klass->has_failure and store a MonoErrorBoxed with the details.
3339 * LOCKING: Acquires the loader lock.
3342 setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite)
3346 int i, j, num_ifaces;
3348 MonoClass **interfaces_full = NULL;
3349 int *interface_offsets_full = NULL;
3351 GPtrArray **ifaces_array = NULL;
3352 int interface_offsets_count;
3354 mono_loader_lock ();
3356 mono_class_setup_supertypes (klass);
3358 /* compute maximum number of slots and maximum interface id */
3360 num_ifaces = 0; /* this can include duplicated ones */
3361 ifaces_array = g_new0 (GPtrArray *, klass->idepth);
3362 for (j = 0; j < klass->idepth; j++) {
3363 k = klass->supertypes [j];
3365 num_ifaces += k->interface_count;
3366 for (i = 0; i < k->interface_count; i++) {
3367 ic = k->interfaces [i];
3369 mono_class_init (ic);
3371 if (max_iid < ic->interface_id)
3372 max_iid = ic->interface_id;
3374 ifaces = mono_class_get_implemented_interfaces (k, &error);
3375 if (!mono_error_ok (&error)) {
3376 char *name = mono_type_get_full_name (k);
3377 mono_class_set_type_load_failure (klass, "Error getting the interfaces of %s due to %s", name, mono_error_get_message (&error));
3379 mono_error_cleanup (&error);
3384 num_ifaces += ifaces->len;
3385 for (i = 0; i < ifaces->len; ++i) {
3386 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3387 if (max_iid < ic->interface_id)
3388 max_iid = ic->interface_id;
3390 ifaces_array [j] = ifaces;
3394 if (MONO_CLASS_IS_INTERFACE (klass)) {
3396 if (max_iid < klass->interface_id)
3397 max_iid = klass->interface_id;
3400 /* compute vtable offset for interfaces */
3401 interfaces_full = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3402 interface_offsets_full = (int *)g_malloc (sizeof (int) * num_ifaces);
3404 for (i = 0; i < num_ifaces; i++)
3405 interface_offsets_full [i] = -1;
3407 /* skip the current class */
3408 for (j = 0; j < klass->idepth - 1; j++) {
3409 k = klass->supertypes [j];
3410 ifaces = ifaces_array [j];
3413 for (i = 0; i < ifaces->len; ++i) {
3415 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3417 /*Force the sharing of interface offsets between parent and subtypes.*/
3418 io = mono_class_interface_offset (k, ic);
3420 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3425 g_assert (klass == klass->supertypes [klass->idepth - 1]);
3426 ifaces = ifaces_array [klass->idepth - 1];
3428 for (i = 0; i < ifaces->len; ++i) {
3430 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3431 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3433 count = count_virtual_methods (ic);
3435 char *name = mono_type_get_full_name (ic);
3436 mono_class_set_type_load_failure (klass, "Error calculating interface offset of %s", name);
3445 if (MONO_CLASS_IS_INTERFACE (klass))
3446 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, klass, cur_slot, TRUE);
3448 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3449 if (interface_offsets_full [i] != -1)
3450 interface_offsets_count ++;
3453 /* Publish the data */
3454 klass->max_interface_id = max_iid;
3456 * We might get called multiple times:
3457 * - mono_class_init ()
3458 * - mono_class_setup_vtable ().
3459 * - mono_class_setup_interface_offsets ().
3460 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3461 * means we have to overwrite those when called from other places (#4440).
3463 if (klass->interfaces_packed) {
3465 g_assert (klass->interface_offsets_count == interface_offsets_count);
3469 klass->interface_offsets_count = interface_offsets_count;
3470 klass->interfaces_packed = (MonoClass **)mono_class_alloc (klass, sizeof (MonoClass*) * interface_offsets_count);
3471 klass->interface_offsets_packed = (guint16 *)mono_class_alloc (klass, sizeof (guint16) * interface_offsets_count);
3472 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3473 #ifdef COMPRESSED_INTERFACE_BITMAP
3474 bitmap = g_malloc0 (bsize);
3476 bitmap = (uint8_t *)mono_class_alloc0 (klass, bsize);
3478 for (i = 0; i < interface_offsets_count; i++) {
3479 guint32 id = interfaces_full [i]->interface_id;
3480 bitmap [id >> 3] |= (1 << (id & 7));
3481 klass->interfaces_packed [i] = interfaces_full [i];
3482 klass->interface_offsets_packed [i] = interface_offsets_full [i];
3484 #ifdef COMPRESSED_INTERFACE_BITMAP
3485 i = mono_compress_bitmap (NULL, bitmap, bsize);
3486 klass->interface_bitmap = mono_class_alloc0 (klass, i);
3487 mono_compress_bitmap (klass->interface_bitmap, bitmap, bsize);
3490 klass->interface_bitmap = bitmap;
3494 mono_loader_unlock ();
3496 g_free (interfaces_full);
3497 g_free (interface_offsets_full);
3498 for (i = 0; i < klass->idepth; i++) {
3499 ifaces = ifaces_array [i];
3501 g_ptr_array_free (ifaces, TRUE);
3503 g_free (ifaces_array);
3505 //printf ("JUST DONE: ");
3506 //print_implemented_interfaces (klass);
3512 * Setup interface offsets for interfaces.
3514 * - klass->max_interface_id
3515 * - klass->interface_offsets_count
3516 * - klass->interfaces_packed
3517 * - klass->interface_offsets_packed
3518 * - klass->interface_bitmap
3520 * This function can fail @class.
3523 mono_class_setup_interface_offsets (MonoClass *klass)
3525 setup_interface_offsets (klass, 0, FALSE);
3528 /*Checks if @klass has @parent as one of it's parents type gtd
3532 * Bar<T> : Foo<Bar<Bar<T>>>
3536 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3538 klass = mono_class_get_generic_type_definition (klass);
3539 parent = mono_class_get_generic_type_definition (parent);
3540 mono_class_setup_supertypes (klass);
3541 mono_class_setup_supertypes (parent);
3543 return klass->idepth >= parent->idepth &&
3544 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3548 mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup)
3550 MonoGenericInst *ginst;
3553 if (!mono_class_is_ginst (klass)) {
3554 mono_class_setup_vtable_full (klass, in_setup);
3555 return !mono_class_has_failure (klass);
3558 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup);
3559 if (mono_class_set_type_load_failure_causedby_class (klass, mono_class_get_generic_class (klass)->container_class, "Failed to load generic definition vtable"))
3562 ginst = mono_class_get_generic_class (klass)->context.class_inst;
3563 for (i = 0; i < ginst->type_argc; ++i) {
3565 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3567 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3568 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3569 if (mono_class_has_gtd_parent (klass, arg) || mono_class_has_gtd_parent (arg, klass))
3571 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3572 mono_class_set_type_load_failure (klass, "Failed to load generic parameter %d", i);
3580 * mono_class_setup_vtable:
3582 * Creates the generic vtable of CLASS.
3583 * Initializes the following fields in MonoClass:
3586 * Plus all the fields initialized by setup_interface_offsets ().
3587 * If there is an error during vtable construction, klass->has_failure
3588 * is set and details are stored in a MonoErrorBoxed.
3590 * LOCKING: Acquires the loader lock.
3593 mono_class_setup_vtable (MonoClass *klass)
3595 mono_class_setup_vtable_full (klass, NULL);
3599 mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
3602 MonoMethod **overrides;
3603 MonoGenericContext *context;
3611 if (MONO_CLASS_IS_INTERFACE (klass)) {
3612 /* This sets method->slot for all methods if this is an interface */
3613 mono_class_setup_methods (klass);
3617 if (mono_class_has_failure (klass))
3620 if (g_list_find (in_setup, klass))
3623 mono_loader_lock ();
3625 if (klass->vtable) {
3626 mono_loader_unlock ();
3630 mono_stats.generic_vtable_count ++;
3631 in_setup = g_list_prepend (in_setup, klass);
3633 if (mono_class_is_ginst (klass)) {
3634 if (!mono_class_check_vtable_constraints (klass, in_setup)) {
3635 mono_loader_unlock ();
3636 g_list_remove (in_setup, klass);
3640 context = mono_class_get_context (klass);
3641 type_token = mono_class_get_generic_class (klass)->container_class->type_token;
3643 context = (MonoGenericContext *) mono_class_try_get_generic_container (klass); //FIXME is this a case of a try?
3644 type_token = klass->type_token;
3647 if (image_is_dynamic (klass->image)) {
3648 /* Generic instances can have zero method overrides without causing any harm.
3649 * This is true since we don't do layout all over again for them, we simply inflate
3650 * the layout of the parent.
3652 mono_reflection_get_dynamic_overrides (klass, &overrides, &onum, &error);
3653 if (!is_ok (&error)) {
3654 mono_loader_unlock ();
3655 g_list_remove (in_setup, klass);
3656 mono_class_set_type_load_failure (klass, "Could not load list of method overrides due to %s", mono_error_get_message (&error));
3657 mono_error_cleanup (&error);
3661 /* The following call fails if there are missing methods in the type */
3662 /* FIXME it's probably a good idea to avoid this for generic instances. */
3663 ok = mono_class_get_overrides_full (klass->image, type_token, &overrides, &onum, context);
3667 mono_class_setup_vtable_general (klass, overrides, onum, in_setup);
3669 mono_class_set_type_load_failure (klass, "Could not load list of method overrides");
3673 mono_loader_unlock ();
3674 g_list_remove (in_setup, klass);
3679 #define DEBUG_INTERFACE_VTABLE_CODE 0
3680 #define TRACE_INTERFACE_VTABLE_CODE 0
3681 #define VERIFY_INTERFACE_VTABLE_CODE 0
3682 #define VTABLE_SELECTOR (1)
3684 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3685 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3686 if (!(VTABLE_SELECTOR)) break; \
3690 #define DEBUG_INTERFACE_VTABLE(stmt)
3693 #if TRACE_INTERFACE_VTABLE_CODE
3694 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3695 if (!(VTABLE_SELECTOR)) break; \
3699 #define TRACE_INTERFACE_VTABLE(stmt)
3702 #if VERIFY_INTERFACE_VTABLE_CODE
3703 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3704 if (!(VTABLE_SELECTOR)) break; \
3708 #define VERIFY_INTERFACE_VTABLE(stmt)
3712 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3714 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3718 GString *res = g_string_new ("");
3720 g_string_append_c (res, '(');
3721 for (i = 0; i < sig->param_count; ++i) {
3723 g_string_append_c (res, ',');
3724 mono_type_get_desc (res, sig->params [i], include_namespace);
3726 g_string_append (res, ")=>");
3727 if (sig->ret != NULL) {
3728 mono_type_get_desc (res, sig->ret, include_namespace);
3730 g_string_append (res, "NULL");
3733 g_string_free (res, FALSE);
3737 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3738 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3739 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3740 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3748 is_wcf_hack_disabled (void)
3750 static gboolean disabled;
3751 static gboolean inited = FALSE;
3753 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3760 check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
3762 MonoMethodSignature *cmsig, *imsig;
3763 if (strcmp (im->name, cm->name) == 0) {
3764 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3765 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3768 if (! slot_is_empty) {
3769 if (require_newslot) {
3770 if (! interface_is_explicitly_implemented_by_class) {
3771 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3774 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3775 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3779 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3782 cmsig = mono_method_signature (cm);
3783 imsig = mono_method_signature (im);
3784 if (!cmsig || !imsig) {
3785 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
3789 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3790 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3791 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3792 TRACE_INTERFACE_VTABLE (printf ("]"));
3795 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3796 if (mono_security_core_clr_enabled ())
3797 mono_security_core_clr_check_override (klass, cm, im);
3799 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
3800 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3801 char *body_name = mono_method_full_name (cm, TRUE);
3802 char *decl_name = mono_method_full_name (im, TRUE);
3803 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
3811 MonoClass *ic = im->klass;
3812 const char *ic_name_space = ic->name_space;
3813 const char *ic_name = ic->name;
3816 if (! require_newslot) {
3817 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
3820 if (cm->klass->rank == 0) {
3821 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
3824 cmsig = mono_method_signature (cm);
3825 imsig = mono_method_signature (im);
3826 if (!cmsig || !imsig) {
3827 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
3831 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3832 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
3833 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3834 TRACE_INTERFACE_VTABLE (printf ("]"));
3837 if (mono_class_get_image (ic) != mono_defaults.corlib) {
3838 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
3841 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
3842 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
3845 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))) {
3846 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
3850 subname = strstr (cm->name, ic_name_space);
3851 if (subname != cm->name) {
3852 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
3855 subname += strlen (ic_name_space);
3856 if (subname [0] != '.') {
3857 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
3861 if (strstr (subname, ic_name) != subname) {
3862 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
3865 subname += strlen (ic_name);
3866 if (subname [0] != '.') {
3867 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
3871 if (strcmp (subname, im->name) != 0) {
3872 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
3876 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
3877 if (mono_security_core_clr_enabled ())
3878 mono_security_core_clr_check_override (klass, cm, im);
3880 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
3881 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3882 char *body_name = mono_method_full_name (cm, TRUE);
3883 char *decl_name = mono_method_full_name (im, TRUE);
3884 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
3894 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3896 foreach_override (gpointer key, gpointer value, gpointer user_data) {
3897 MonoMethod *method = key;
3898 MonoMethod *override = value;
3899 MonoClass *method_class = mono_method_get_class (method);
3900 MonoClass *override_class = mono_method_get_class (override);
3902 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
3903 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
3904 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
3907 print_overrides (GHashTable *override_map, const char *message) {
3909 printf ("Override map \"%s\" START:\n", message);
3910 g_hash_table_foreach (override_map, foreach_override, NULL);
3911 printf ("Override map \"%s\" END.\n", message);
3913 printf ("Override map \"%s\" EMPTY.\n", message);
3917 print_vtable_full (MonoClass *klass, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
3918 char *full_name = mono_type_full_name (&klass->byval_arg);
3922 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
3924 if (print_interfaces) {
3925 print_implemented_interfaces (klass);
3926 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
3929 if (klass->parent) {
3930 parent_size = klass->parent->vtable_size;
3934 for (i = 0; i < size; ++i) {
3935 MonoMethod *cm = vtable [i];
3936 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
3937 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
3939 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
3947 #if VERIFY_INTERFACE_VTABLE_CODE
3949 mono_method_try_get_vtable_index (MonoMethod *method)
3951 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
3952 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
3953 if (imethod->declaring->is_generic)
3954 return imethod->declaring->slot;
3956 return method->slot;
3960 mono_class_verify_vtable (MonoClass *klass)
3963 char *full_name = mono_type_full_name (&klass->byval_arg);
3965 printf ("*** Verifying VTable of class '%s' \n", full_name);
3969 if (!klass->methods)
3972 count = mono_class_method_count (klass);
3973 for (i = 0; i < count; ++i) {
3974 MonoMethod *cm = klass->methods [i];
3977 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
3981 full_name = mono_method_full_name (cm, TRUE);
3983 slot = mono_method_try_get_vtable_index (cm);
3985 if (slot >= klass->vtable_size) {
3986 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, klass->vtable_size);
3990 if (slot >= 0 && klass->vtable [slot] != cm && (klass->vtable [slot])) {
3991 char *other_name = klass->vtable [slot] ? mono_method_full_name (klass->vtable [slot], TRUE) : g_strdup ("[null value]");
3992 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
3993 g_free (other_name);
3996 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4003 print_unimplemented_interface_method_info (MonoClass *klass, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum)
4006 char *method_signature;
4009 for (index = 0; index < onum; ++index) {
4010 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)", im_slot, overrides [index*2+1]->name,
4011 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4013 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4014 type_name = mono_type_full_name (&klass->byval_arg);
4015 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s",
4016 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4017 g_free (method_signature);
4019 mono_class_setup_methods (klass);
4020 if (mono_class_has_failure (klass)) {
4021 char *name = mono_type_get_full_name (klass);
4022 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods", name);
4026 mcount = mono_class_get_method_count (klass);
4027 for (index = 0; index < mcount; ++index) {
4028 MonoMethod *cm = klass->methods [index];
4029 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4031 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)", cm->name, method_signature);
4032 g_free (method_signature);
4037 mono_method_get_method_definition (MonoMethod *method)
4039 while (method->is_inflated)
4040 method = ((MonoMethodInflated*)method)->declaring;
4045 verify_class_overrides (MonoClass *klass, MonoMethod **overrides, int onum)
4049 for (i = 0; i < onum; ++i) {
4050 MonoMethod *decl = overrides [i * 2];
4051 MonoMethod *body = overrides [i * 2 + 1];
4053 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (klass)) {
4054 mono_class_set_type_load_failure (klass, "Method belongs to a different class than the declared one");
4058 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4059 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4060 mono_class_set_type_load_failure (klass, "Method must not be static to override a base type");
4062 mono_class_set_type_load_failure (klass, "Method must be virtual to override a base type");
4066 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4067 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4068 mono_class_set_type_load_failure (klass, "Cannot override a static method in a base type");
4070 mono_class_set_type_load_failure (klass, "Cannot override a non virtual method in a base type");
4074 if (!mono_class_is_assignable_from_slow (decl->klass, klass)) {
4075 mono_class_set_type_load_failure (klass, "Method overrides a class or interface that is not extended or implemented by this type");
4079 body = mono_method_get_method_definition (body);
4080 decl = mono_method_get_method_definition (decl);
4082 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4083 char *body_name = mono_method_full_name (body, TRUE);
4084 char *decl_name = mono_method_full_name (decl, TRUE);
4085 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4095 mono_class_need_stelemref_method (MonoClass *klass)
4097 return klass->rank == 1 && MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg);
4101 * LOCKING: this is supposed to be called with the loader lock held.
4104 mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int onum, GList *in_setup)
4108 MonoMethod **vtable = NULL;
4109 int i, max_vtsize = 0, cur_slot = 0;
4111 GPtrArray *ifaces = NULL;
4112 GHashTable *override_map = NULL;
4114 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4115 int first_non_interface_slot;
4117 GSList *virt_methods = NULL, *l;
4118 int stelemref_slot = 0;
4123 if (overrides && !verify_class_overrides (klass, overrides, onum))
4126 ifaces = mono_class_get_implemented_interfaces (klass, &error);
4127 if (!mono_error_ok (&error)) {
4128 char *name = mono_type_get_full_name (klass);
4129 mono_class_set_type_load_failure (klass, "Could not resolve %s interfaces due to %s", name, mono_error_get_message (&error));
4131 mono_error_cleanup (&error);
4133 } else if (ifaces) {
4134 for (i = 0; i < ifaces->len; i++) {
4135 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
4136 max_vtsize += mono_class_get_method_count (ic);
4138 g_ptr_array_free (ifaces, TRUE);
4142 if (klass->parent) {
4143 mono_class_init (klass->parent);
4144 mono_class_setup_vtable_full (klass->parent, in_setup);
4146 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class failed to load"))
4149 max_vtsize += klass->parent->vtable_size;
4150 cur_slot = klass->parent->vtable_size;
4153 max_vtsize += mono_class_get_method_count (klass);
4155 /*Array have a slot for stelemref*/
4156 if (mono_class_need_stelemref_method (klass)) {
4157 stelemref_slot = cur_slot;
4162 /* printf ("METAINIT %s.%s\n", klass->name_space, klass->name); */
4164 cur_slot = setup_interface_offsets (klass, cur_slot, TRUE);
4165 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4168 max_iid = klass->max_interface_id;
4169 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4171 /* Optimized version for generic instances */
4172 if (mono_class_is_ginst (klass)) {
4174 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4177 mono_class_setup_vtable_full (gklass, in_setup);
4178 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Could not load generic definition"))
4181 tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * gklass->vtable_size);
4182 klass->vtable_size = gklass->vtable_size;
4183 for (i = 0; i < gklass->vtable_size; ++i)
4184 if (gklass->vtable [i]) {
4185 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], klass, mono_class_get_context (klass), &error);
4186 if (!mono_error_ok (&error)) {
4187 mono_class_set_type_load_failure (klass, "Could not inflate method due to %s", mono_error_get_message (&error));
4188 mono_error_cleanup (&error);
4192 tmp [i]->slot = gklass->vtable [i]->slot;
4194 mono_memory_barrier ();
4195 klass->vtable = tmp;
4197 /* Have to set method->slot for abstract virtual methods */
4198 if (klass->methods && gklass->methods) {
4199 int mcount = mono_class_get_method_count (klass);
4200 for (i = 0; i < mcount; ++i)
4201 if (klass->methods [i]->slot == -1)
4202 klass->methods [i]->slot = gklass->methods [i]->slot;
4208 vtable = (MonoMethod **)g_malloc0 (sizeof (gpointer) * max_vtsize);
4210 if (klass->parent && klass->parent->vtable_size) {
4211 MonoClass *parent = klass->parent;
4214 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4216 // Also inherit parent interface vtables, just as a starting point.
4217 // This is needed otherwise bug-77127.exe fails when the property methods
4218 // have different names in the iterface and the class, because for child
4219 // classes the ".override" information is not used anymore.
4220 for (i = 0; i < parent->interface_offsets_count; i++) {
4221 MonoClass *parent_interface = parent->interfaces_packed [i];
4222 int interface_offset = mono_class_interface_offset (klass, parent_interface);
4223 /*FIXME this is now dead code as this condition will never hold true.
4224 Since interface offsets are inherited then the offset of an interface implemented
4225 by a parent will never be the out of it's vtable boundary.
4227 if (interface_offset >= parent->vtable_size) {
4228 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4231 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4232 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4233 int mcount = mono_class_get_method_count (parent_interface);
4234 for (j = 0; j < mcount && !mono_class_has_failure (klass); j++) {
4235 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4236 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4237 parent_interface_offset + j, parent_interface_offset, j,
4238 interface_offset + j, interface_offset, j));
4245 /*Array have a slot for stelemref*/
4246 if (mono_class_need_stelemref_method (klass)) {
4247 MonoMethod *method = mono_marshal_get_virtual_stelemref (klass);
4249 method->slot = stelemref_slot;
4251 g_assert (method->slot == stelemref_slot);
4253 vtable [stelemref_slot] = method;
4256 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4257 /* override interface methods */
4258 for (i = 0; i < onum; i++) {
4259 MonoMethod *decl = overrides [i*2];
4260 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4262 dslot = mono_method_get_vtable_slot (decl);
4264 mono_class_set_type_load_failure (klass, "");
4268 dslot += mono_class_interface_offset (klass, decl->klass);
4269 vtable [dslot] = overrides [i*2 + 1];
4270 vtable [dslot]->slot = dslot;
4272 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4274 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4276 if (mono_security_core_clr_enabled ())
4277 mono_security_core_clr_check_override (klass, vtable [dslot], decl);
4280 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4281 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4284 * Create a list of virtual methods to avoid calling
4285 * mono_class_get_virtual_methods () which is slow because of the metadata
4289 gpointer iter = NULL;
4292 virt_methods = NULL;
4293 while ((cm = mono_class_get_virtual_methods (klass, &iter))) {
4294 virt_methods = g_slist_prepend (virt_methods, cm);
4296 if (mono_class_has_failure (klass))
4300 // Loop on all implemented interfaces...
4301 for (i = 0; i < klass->interface_offsets_count; i++) {
4302 MonoClass *parent = klass->parent;
4304 gboolean interface_is_explicitly_implemented_by_class;
4307 ic = klass->interfaces_packed [i];
4308 ic_offset = mono_class_interface_offset (klass, ic);
4310 mono_class_setup_methods (ic);
4311 if (mono_class_has_failure (ic))
4314 // Check if this interface is explicitly implemented (instead of just inherited)
4315 if (parent != NULL) {
4316 int implemented_interfaces_index;
4317 interface_is_explicitly_implemented_by_class = FALSE;
4318 for (implemented_interfaces_index = 0; implemented_interfaces_index < klass->interface_count; implemented_interfaces_index++) {
4319 if (ic == klass->interfaces [implemented_interfaces_index]) {
4320 interface_is_explicitly_implemented_by_class = TRUE;
4325 interface_is_explicitly_implemented_by_class = TRUE;
4328 // Loop on all interface methods...
4329 int mcount = mono_class_get_method_count (ic);
4330 for (im_index = 0; im_index < mcount; im_index++) {
4331 MonoMethod *im = ic->methods [im_index];
4332 int im_slot = ic_offset + im->slot;
4333 MonoMethod *override_im = (override_map != NULL) ? (MonoMethod *)g_hash_table_lookup (override_map, im) : NULL;
4335 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4338 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4340 // If there is an explicit implementation, just use it right away,
4341 // otherwise look for a matching method
4342 if (override_im == NULL) {
4346 // First look for a suitable method among the class methods
4347 for (l = virt_methods; l; l = l->next) {
4348 cm = (MonoMethod *)l->data;
4349 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)));
4350 if (check_interface_method_override (klass, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
4351 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4352 vtable [im_slot] = cm;
4353 /* Why do we need this? */
4358 TRACE_INTERFACE_VTABLE (printf ("\n"));
4359 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4363 // If the slot is still empty, look in all the inherited virtual methods...
4364 if ((vtable [im_slot] == NULL) && klass->parent != NULL) {
4365 MonoClass *parent = klass->parent;
4366 // Reverse order, so that last added methods are preferred
4367 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4368 MonoMethod *cm = parent->vtable [cm_index];
4370 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));
4371 if ((cm != NULL) && check_interface_method_override (klass, im, cm, FALSE, FALSE, TRUE)) {
4372 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4373 vtable [im_slot] = cm;
4374 /* Why do we need this? */
4380 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4382 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4386 g_assert (vtable [im_slot] == override_im);
4391 // If the class is not abstract, check that all its interface slots are full.
4392 // The check is done here and not directly at the end of the loop above because
4393 // it can happen (for injected generic array interfaces) that the same slot is
4394 // processed multiple times (those interfaces have overlapping slots), and it
4395 // will not always be the first pass the one that fills the slot.
4396 if (!mono_class_is_abstract (klass)) {
4397 for (i = 0; i < klass->interface_offsets_count; i++) {
4401 ic = klass->interfaces_packed [i];
4402 ic_offset = mono_class_interface_offset (klass, ic);
4404 int mcount = mono_class_get_method_count (ic);
4405 for (im_index = 0; im_index < mcount; im_index++) {
4406 MonoMethod *im = ic->methods [im_index];
4407 int im_slot = ic_offset + im->slot;
4409 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4412 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4413 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4414 if (vtable [im_slot] == NULL) {
4415 print_unimplemented_interface_method_info (klass, ic, im, im_slot, overrides, onum);
4422 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4423 for (l = virt_methods; l; l = l->next) {
4424 cm = (MonoMethod *)l->data;
4426 * If the method is REUSE_SLOT, we must check in the
4427 * base class for a method to override.
4429 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4431 for (k = klass->parent; k ; k = k->parent) {
4436 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4437 MonoMethodSignature *cmsig, *m1sig;
4439 cmsig = mono_method_signature (cm);
4440 m1sig = mono_method_signature (m1);
4442 if (!cmsig || !m1sig) {
4443 /* FIXME proper error message */
4444 mono_class_set_type_load_failure (klass, "");
4448 if (!strcmp(cm->name, m1->name) &&
4449 mono_metadata_signature_equal (cmsig, m1sig)) {
4451 if (mono_security_core_clr_enabled ())
4452 mono_security_core_clr_check_override (klass, cm, m1);
4454 slot = mono_method_get_vtable_slot (m1);
4458 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4459 char *body_name = mono_method_full_name (cm, TRUE);
4460 char *decl_name = mono_method_full_name (m1, TRUE);
4461 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4467 g_assert (cm->slot < max_vtsize);
4469 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4470 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4471 mono_method_full_name (m1, 1), m1,
4472 mono_method_full_name (cm, 1), cm));
4473 g_hash_table_insert (override_map, m1, cm);
4477 if (mono_class_has_failure (k))
4487 /*Non final newslot methods must be given a non-interface vtable slot*/
4488 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4492 cm->slot = cur_slot++;
4494 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4495 vtable [cm->slot] = cm;
4498 /* override non interface methods */
4499 for (i = 0; i < onum; i++) {
4500 MonoMethod *decl = overrides [i*2];
4501 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4502 g_assert (decl->slot != -1);
4503 vtable [decl->slot] = overrides [i*2 + 1];
4504 overrides [i * 2 + 1]->slot = decl->slot;
4506 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4507 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4508 mono_method_full_name (decl, 1), decl,
4509 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4510 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4512 if (mono_security_core_clr_enabled ())
4513 mono_security_core_clr_check_override (klass, vtable [decl->slot], decl);
4518 * If a method occupies more than one place in the vtable, and it is
4519 * overriden, then change the other occurances too.
4524 for (i = 0; i < max_vtsize; ++i)
4526 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4528 cm = (MonoMethod *)g_hash_table_lookup (override_map, vtable [i]);
4533 g_hash_table_destroy (override_map);
4534 override_map = NULL;
4537 g_slist_free (virt_methods);
4538 virt_methods = NULL;
4540 g_assert (cur_slot <= max_vtsize);
4542 /* Ensure that all vtable slots are filled with concrete instance methods */
4543 if (!mono_class_is_abstract (klass)) {
4544 for (i = 0; i < cur_slot; ++i) {
4545 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4546 char *type_name = mono_type_get_full_name (klass);
4547 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4548 mono_class_set_type_load_failure (klass, "Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name);
4550 g_free (method_name);
4557 if (mono_class_is_ginst (klass)) {
4558 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4560 mono_class_init (gklass);
4562 klass->vtable_size = MAX (gklass->vtable_size, cur_slot);
4564 /* Check that the vtable_size value computed in mono_class_init () is correct */
4565 if (klass->vtable_size)
4566 g_assert (cur_slot == klass->vtable_size);
4567 klass->vtable_size = cur_slot;
4570 /* Try to share the vtable with our parent. */
4571 if (klass->parent && (klass->parent->vtable_size == klass->vtable_size) && (memcmp (klass->parent->vtable, vtable, sizeof (gpointer) * klass->vtable_size) == 0)) {
4572 mono_memory_barrier ();
4573 klass->vtable = klass->parent->vtable;
4575 MonoMethod **tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * klass->vtable_size);
4576 memcpy (tmp, vtable, sizeof (gpointer) * klass->vtable_size);
4577 mono_memory_barrier ();
4578 klass->vtable = tmp;
4581 DEBUG_INTERFACE_VTABLE (print_vtable_full (klass, klass->vtable, klass->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4582 if (mono_print_vtable) {
4585 print_implemented_interfaces (klass);
4587 for (i = 0; i <= max_iid; i++)
4588 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
4591 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&klass->byval_arg),
4592 klass->vtable_size, icount);
4594 for (i = 0; i < cur_slot; ++i) {
4599 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4600 mono_method_full_name (cm, TRUE));
4606 printf ("Interfaces %s.%s (max_iid = %d)\n", klass->name_space,
4607 klass->name, max_iid);
4609 for (i = 0; i < klass->interface_count; i++) {
4610 ic = klass->interfaces [i];
4611 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4612 mono_class_interface_offset (klass, ic),
4613 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4616 for (k = klass->parent; k ; k = k->parent) {
4617 for (i = 0; i < k->interface_count; i++) {
4618 ic = k->interfaces [i];
4619 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4620 mono_class_interface_offset (klass, ic),
4621 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4629 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (klass));
4634 char *name = mono_type_get_full_name (klass);
4635 mono_class_set_type_load_failure (klass, "VTable setup of type %s failed", name);
4639 g_hash_table_destroy (override_map);
4641 g_slist_free (virt_methods);
4646 * mono_method_get_vtable_slot:
4648 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4649 * LOCKING: Acquires the loader lock.
4651 * FIXME Use proper MonoError machinery here.
4654 mono_method_get_vtable_slot (MonoMethod *method)
4656 if (method->slot == -1) {
4657 mono_class_setup_vtable (method->klass);
4658 if (mono_class_has_failure (method->klass))
4660 if (method->slot == -1) {
4664 if (!mono_class_is_ginst (method->klass)) {
4665 g_assert (method->is_inflated);
4666 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4669 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4670 g_assert (mono_class_is_ginst (method->klass));
4671 gklass = mono_class_get_generic_class (method->klass)->container_class;
4672 mono_class_setup_methods (method->klass);
4673 g_assert (method->klass->methods);
4674 mcount = mono_class_get_method_count (method->klass);
4675 for (i = 0; i < mcount; ++i) {
4676 if (method->klass->methods [i] == method)
4679 g_assert (i < mcount);
4680 g_assert (gklass->methods);
4681 method->slot = gklass->methods [i]->slot;
4683 g_assert (method->slot != -1);
4685 return method->slot;
4689 * mono_method_get_vtable_index:
4692 * Returns the index into the runtime vtable to access the method or,
4693 * in the case of a virtual generic method, the virtual generic method
4694 * thunk. Returns -1 on failure.
4696 * FIXME Use proper MonoError machinery here.
4699 mono_method_get_vtable_index (MonoMethod *method)
4701 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4702 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4703 if (imethod->declaring->is_generic)
4704 return mono_method_get_vtable_slot (imethod->declaring);
4706 return mono_method_get_vtable_slot (method);
4709 static MonoMethod *default_ghc = NULL;
4710 static MonoMethod *default_finalize = NULL;
4711 static int finalize_slot = -1;
4712 static int ghc_slot = -1;
4715 initialize_object_slots (MonoClass *klass)
4720 if (klass == mono_defaults.object_class) {
4721 mono_class_setup_vtable (klass);
4722 for (i = 0; i < klass->vtable_size; ++i) {
4723 MonoMethod *cm = klass->vtable [i];
4725 if (!strcmp (cm->name, "GetHashCode"))
4727 else if (!strcmp (cm->name, "Finalize"))
4731 g_assert (ghc_slot > 0);
4732 default_ghc = klass->vtable [ghc_slot];
4734 g_assert (finalize_slot > 0);
4735 default_finalize = klass->vtable [finalize_slot];
4740 MonoMethod *array_method;
4742 } GenericArrayMethodInfo;
4744 static int generic_array_method_num = 0;
4745 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4748 generic_array_methods (MonoClass *klass)
4750 int i, count_generic = 0, mcount;
4751 GList *list = NULL, *tmp;
4752 if (generic_array_method_num)
4753 return generic_array_method_num;
4754 mono_class_setup_methods (klass->parent); /*This is setting up System.Array*/
4755 g_assert (!mono_class_has_failure (klass->parent)); /*So hitting this assert is a huge problem*/
4756 mcount = mono_class_get_method_count (klass->parent);
4757 for (i = 0; i < mcount; i++) {
4758 MonoMethod *m = klass->parent->methods [i];
4759 if (!strncmp (m->name, "InternalArray__", 15)) {
4761 list = g_list_prepend (list, m);
4764 list = g_list_reverse (list);
4765 generic_array_method_info = (GenericArrayMethodInfo *)mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4767 for (tmp = list; tmp; tmp = tmp->next) {
4768 const char *mname, *iname;
4770 MonoMethod *m = (MonoMethod *)tmp->data;
4771 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4772 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4774 generic_array_method_info [i].array_method = m;
4775 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4776 iname = "System.Collections.Generic.ICollection`1.";
4777 mname = m->name + 27;
4778 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4779 iname = "System.Collections.Generic.IEnumerable`1.";
4780 mname = m->name + 27;
4781 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4782 iname = "System.Collections.Generic.IReadOnlyList`1.";
4783 mname = m->name + strlen (ireadonlylist_prefix);
4784 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4785 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4786 mname = m->name + strlen (ireadonlycollection_prefix);
4787 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4788 iname = "System.Collections.Generic.IList`1.";
4789 mname = m->name + 15;
4791 g_assert_not_reached ();
4794 name = (gchar *)mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4795 strcpy (name, iname);
4796 strcpy (name + strlen (iname), mname);
4797 generic_array_method_info [i].name = name;
4800 /*g_print ("array generic methods: %d\n", count_generic);*/
4802 generic_array_method_num = count_generic;
4804 return generic_array_method_num;
4808 setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos)
4810 MonoGenericContext tmp_context;
4813 tmp_context.class_inst = NULL;
4814 tmp_context.method_inst = mono_class_get_generic_class (iface)->context.class_inst;
4815 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
4817 for (i = 0; i < generic_array_method_num; i++) {
4819 MonoMethod *m = generic_array_method_info [i].array_method;
4820 MonoMethod *inflated;
4822 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
4823 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
4824 methods [pos++] = mono_marshal_get_generic_array_helper (klass, iface, generic_array_method_info [i].name, inflated);
4829 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
4831 int null_length = strlen ("(null)");
4832 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
4833 char *s = (char *)mono_image_alloc (image, len);
4836 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
4837 g_assert (result == len - 1);
4844 * @klass: the class to initialize
4846 * Compute the instance_size, class_size and other infos that cannot be
4847 * computed at mono_class_get() time. Also compute vtable_size if possible.
4848 * Returns TRUE on success or FALSE if there was a problem in loading
4849 * the type (incorrect assemblies, missing assemblies, methods, etc).
4850 * Initializes the following fields in @klass:
4851 * - all the fields initialized by mono_class_init_sizes ()
4856 * LOCKING: Acquires the loader lock.
4859 mono_class_init (MonoClass *klass)
4861 int i, vtable_size = 0, array_method_count = 0;
4862 MonoCachedClassInfo cached_info;
4863 gboolean has_cached_info;
4864 gboolean locked = FALSE;
4865 gboolean ghcimpl = FALSE;
4866 gboolean has_cctor = FALSE;
4867 int first_iface_slot = 0;
4871 /* Double-checking locking pattern */
4872 if (klass->inited || mono_class_has_failure (klass))
4873 return !mono_class_has_failure (klass);
4875 /*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/
4878 * This function can recursively call itself.
4880 GSList *init_list = (GSList *)mono_native_tls_get_value (init_pending_tls_id);
4881 if (g_slist_find (init_list, klass)) {
4882 mono_class_set_type_load_failure (klass, "Recursive type definition detected");
4885 init_list = g_slist_prepend (init_list, klass);
4886 mono_native_tls_set_value (init_pending_tls_id, init_list);
4889 * We want to avoid doing complicated work inside locks, so we compute all the required
4890 * information and write it to @klass inside a lock.
4893 if (mono_verifier_is_enabled_for_class (klass) && !mono_verifier_verify_class (klass)) {
4894 mono_class_set_type_load_failure (klass, "%s", concat_two_strings_with_zero (klass->image, klass->name, klass->image->assembly_name));
4898 if (klass->byval_arg.type == MONO_TYPE_ARRAY || klass->byval_arg.type == MONO_TYPE_SZARRAY) {
4899 MonoClass *element_class = klass->element_class;
4900 if (!element_class->inited)
4901 mono_class_init (element_class);
4902 if (mono_class_set_type_load_failure_causedby_class (klass, element_class, "Could not load array element class"))
4906 mono_stats.initialized_class_count++;
4908 if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic) {
4909 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4911 mono_class_init (gklass);
4912 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic Type Definition failed to init"))
4915 mono_class_setup_interface_id (klass);
4918 if (klass->parent && !klass->parent->inited)
4919 mono_class_init (klass->parent);
4921 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
4923 /* Compute instance size etc. */
4924 init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
4925 if (mono_class_has_failure (klass))
4928 mono_class_setup_supertypes (klass);
4931 initialize_object_slots (klass);
4934 * Initialize the rest of the data without creating a generic vtable if possible.
4935 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
4936 * also avoid computing a generic vtable.
4938 if (has_cached_info) {
4940 vtable_size = cached_info.vtable_size;
4941 ghcimpl = cached_info.ghcimpl;
4942 has_cctor = cached_info.has_cctor;
4943 } else if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
4944 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
4945 * The first slot if for array with.
4947 static int szarray_vtable_size[2] = { 0 };
4949 int slot = MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg) ? 0 : 1;
4952 if (!szarray_vtable_size [slot]) {
4953 mono_class_setup_vtable (klass);
4954 szarray_vtable_size [slot] = klass->vtable_size;
4955 vtable_size = klass->vtable_size;
4957 vtable_size = szarray_vtable_size[slot];
4959 } else if (mono_class_is_ginst (klass) && !MONO_CLASS_IS_INTERFACE (klass)) {
4960 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4962 /* Generic instance case */
4963 ghcimpl = gklass->ghcimpl;
4964 has_cctor = gklass->has_cctor;
4966 mono_class_setup_vtable (gklass);
4967 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to init"))
4970 vtable_size = gklass->vtable_size;
4974 /* ghcimpl is not currently used
4976 if (klass->parent) {
4977 MonoMethod *cmethod = klass->vtable [ghc_slot];
4978 if (cmethod->is_inflated)
4979 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
4980 if (cmethod == default_ghc) {
4986 /* C# doesn't allow interfaces to have cctors */
4987 if (!MONO_CLASS_IS_INTERFACE (klass) || klass->image != mono_defaults.corlib) {
4988 MonoMethod *cmethod = NULL;
4990 if (mono_class_is_ginst (klass)) {
4991 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4993 /* Generic instance case */
4994 ghcimpl = gklass->ghcimpl;
4995 has_cctor = gklass->has_cctor;
4996 } else if (klass->type_token && !image_is_dynamic(klass->image)) {
4997 cmethod = find_method_in_metadata (klass, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
4998 /* The find_method function ignores the 'flags' argument */
4999 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5002 mono_class_setup_methods (klass);
5003 if (mono_class_has_failure (klass))
5006 int mcount = mono_class_get_method_count (klass);
5007 for (i = 0; i < mcount; ++i) {
5008 MonoMethod *method = klass->methods [i];
5009 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5010 (strcmp (".cctor", method->name) == 0)) {
5020 array_method_count = 3 + (klass->rank > 1? 2: 1);
5022 if (klass->interface_count) {
5023 int count_generic = generic_array_methods (klass);
5024 array_method_count += klass->interface_count * count_generic;
5028 if (klass->parent) {
5029 if (!klass->parent->vtable_size)
5030 mono_class_setup_vtable (klass->parent);
5031 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class vtable failed to initialize"))
5033 g_assert (klass->parent->vtable_size);
5034 first_iface_slot = klass->parent->vtable_size;
5035 if (mono_class_need_stelemref_method (klass))
5040 * Do the actual changes to @klass inside the loader lock
5042 mono_loader_lock ();
5045 if (klass->inited || mono_class_has_failure (klass)) {
5046 mono_loader_unlock ();
5047 /* Somebody might have gotten in before us */
5048 return !mono_class_has_failure (klass);
5051 mono_stats.initialized_class_count++;
5053 if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic)
5054 mono_stats.generic_class_count++;
5056 if (mono_class_is_ginst (klass) || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
5057 klass->nested_classes_inited = TRUE;
5058 klass->ghcimpl = ghcimpl;
5059 klass->has_cctor = has_cctor;
5061 klass->vtable_size = vtable_size;
5062 if (has_cached_info) {
5063 klass->has_finalize = cached_info.has_finalize;
5064 klass->has_finalize_inited = TRUE;
5067 mono_class_set_method_count (klass, array_method_count);
5069 mono_loader_unlock ();
5072 setup_interface_offsets (klass, first_iface_slot, TRUE);
5074 if (mono_security_core_clr_enabled ())
5075 mono_security_core_clr_check_inheritance (klass);
5077 if (mono_class_is_ginst (klass) && !mono_verifier_class_is_valid_generic_instantiation (klass))
5078 mono_class_set_type_load_failure (klass, "Invalid generic instantiation");
5083 init_list = g_slist_remove (init_list, klass);
5084 mono_native_tls_set_value (init_pending_tls_id, init_list);
5087 mono_loader_unlock ();
5089 /* Leave this for last */
5090 mono_loader_lock ();
5092 mono_loader_unlock ();
5094 return !mono_class_has_failure (klass);
5098 * mono_class_has_finalizer:
5100 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5104 mono_class_has_finalizer (MonoClass *klass)
5106 gboolean has_finalize = FALSE;
5108 if (klass->has_finalize_inited)
5109 return klass->has_finalize;
5111 /* Interfaces and valuetypes are not supposed to have finalizers */
5112 if (!(MONO_CLASS_IS_INTERFACE (klass) || klass->valuetype)) {
5113 MonoMethod *cmethod = NULL;
5115 if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5116 } else if (mono_class_is_ginst (klass)) {
5117 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5119 has_finalize = mono_class_has_finalizer (gklass);
5120 } else if (klass->parent && klass->parent->has_finalize) {
5121 has_finalize = TRUE;
5123 if (klass->parent) {
5125 * Can't search in metadata for a method named Finalize, because that
5126 * ignores overrides.
5128 mono_class_setup_vtable (klass);
5129 if (mono_class_has_failure (klass))
5132 cmethod = klass->vtable [finalize_slot];
5136 g_assert (klass->vtable_size > finalize_slot);
5138 if (klass->parent) {
5139 if (cmethod->is_inflated)
5140 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5141 if (cmethod != default_finalize)
5142 has_finalize = TRUE;
5148 mono_image_lock (klass->image);
5150 if (!klass->has_finalize_inited) {
5151 klass->has_finalize = has_finalize ? 1 : 0;
5153 mono_memory_barrier ();
5154 klass->has_finalize_inited = TRUE;
5157 mono_image_unlock (klass->image);
5159 return klass->has_finalize;
5163 mono_is_corlib_image (MonoImage *image)
5165 return image == mono_defaults.corlib;
5169 * LOCKING: this assumes the loader lock is held
5172 mono_class_setup_mono_type (MonoClass *klass)
5174 const char *name = klass->name;
5175 const char *nspace = klass->name_space;
5176 gboolean is_corlib = mono_is_corlib_image (klass->image);
5178 klass->this_arg.byref = 1;
5179 klass->this_arg.data.klass = klass;
5180 klass->this_arg.type = MONO_TYPE_CLASS;
5181 klass->byval_arg.data.klass = klass;
5182 klass->byval_arg.type = MONO_TYPE_CLASS;
5184 if (is_corlib && !strcmp (nspace, "System")) {
5185 if (!strcmp (name, "ValueType")) {
5187 * do not set the valuetype bit for System.ValueType.
5188 * klass->valuetype = 1;
5190 klass->blittable = TRUE;
5191 } else if (!strcmp (name, "Enum")) {
5193 * do not set the valuetype bit for System.Enum.
5194 * klass->valuetype = 1;
5196 klass->valuetype = 0;
5197 klass->enumtype = 0;
5198 } else if (!strcmp (name, "Object")) {
5199 klass->byval_arg.type = MONO_TYPE_OBJECT;
5200 klass->this_arg.type = MONO_TYPE_OBJECT;
5201 } else if (!strcmp (name, "String")) {
5202 klass->byval_arg.type = MONO_TYPE_STRING;
5203 klass->this_arg.type = MONO_TYPE_STRING;
5204 } else if (!strcmp (name, "TypedReference")) {
5205 klass->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5206 klass->this_arg.type = MONO_TYPE_TYPEDBYREF;
5210 if (klass->valuetype) {
5211 int t = MONO_TYPE_VALUETYPE;
5213 if (is_corlib && !strcmp (nspace, "System")) {
5216 if (!strcmp (name, "Boolean")) {
5217 t = MONO_TYPE_BOOLEAN;
5218 } else if (!strcmp(name, "Byte")) {
5220 klass->blittable = TRUE;
5224 if (!strcmp (name, "Char")) {
5229 if (!strcmp (name, "Double")) {
5231 klass->blittable = TRUE;
5235 if (!strcmp (name, "Int32")) {
5237 klass->blittable = TRUE;
5238 } else if (!strcmp(name, "Int16")) {
5240 klass->blittable = TRUE;
5241 } else if (!strcmp(name, "Int64")) {
5243 klass->blittable = TRUE;
5244 } else if (!strcmp(name, "IntPtr")) {
5246 klass->blittable = TRUE;
5250 if (!strcmp (name, "Single")) {
5252 klass->blittable = TRUE;
5253 } else if (!strcmp(name, "SByte")) {
5255 klass->blittable = TRUE;
5259 if (!strcmp (name, "UInt32")) {
5261 klass->blittable = TRUE;
5262 } else if (!strcmp(name, "UInt16")) {
5264 klass->blittable = TRUE;
5265 } else if (!strcmp(name, "UInt64")) {
5267 klass->blittable = TRUE;
5268 } else if (!strcmp(name, "UIntPtr")) {
5270 klass->blittable = TRUE;
5274 if (!strcmp (name, "TypedReference")) {
5275 t = MONO_TYPE_TYPEDBYREF;
5276 klass->blittable = TRUE;
5280 if (!strcmp (name, "Void")) {
5288 klass->byval_arg.type = (MonoTypeEnum)t;
5289 klass->this_arg.type = (MonoTypeEnum)t;
5292 if (MONO_CLASS_IS_INTERFACE (klass)) {
5293 klass->interface_id = mono_get_unique_iid (klass);
5295 if (is_corlib && !strcmp (nspace, "System.Collections.Generic")) {
5296 //FIXME IEnumerator needs to be special because GetEnumerator uses magic under the hood
5297 /* FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
5298 * MS returns diferrent types based on which instance is called. For example:
5299 * object obj = new byte[10][];
5300 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
5301 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
5304 if (!strcmp (name, "IList`1") || !strcmp (name, "ICollection`1") || !strcmp (name, "IEnumerable`1") || !strcmp (name, "IEnumerator`1"))
5305 klass->is_array_special_interface = 1;
5312 * COM initialization is delayed until needed.
5313 * However when a [ComImport] attribute is present on a type it will trigger
5314 * the initialization. This is not a problem unless the BCL being executed
5315 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5318 init_com_from_comimport (MonoClass *klass)
5320 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5321 if (mono_security_core_clr_enabled ()) {
5322 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5323 if (!mono_security_core_clr_determine_platform_image (klass->image)) {
5324 /* but it can not be made available for application (i.e. user code) since all COM calls
5325 * are considered native calls. In this case we fail with a TypeLoadException (just like
5326 * Silverlight 2 does */
5327 mono_class_set_type_load_failure (klass, "");
5332 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5334 #endif /*DISABLE_COM*/
5337 * LOCKING: this assumes the loader lock is held
5340 mono_class_setup_parent (MonoClass *klass, MonoClass *parent)
5342 gboolean system_namespace;
5343 gboolean is_corlib = mono_is_corlib_image (klass->image);
5345 system_namespace = !strcmp (klass->name_space, "System") && is_corlib;
5347 /* if root of the hierarchy */
5348 if (system_namespace && !strcmp (klass->name, "Object")) {
5349 klass->parent = NULL;
5350 klass->instance_size = sizeof (MonoObject);
5353 if (!strcmp (klass->name, "<Module>")) {
5354 klass->parent = NULL;
5355 klass->instance_size = 0;
5359 if (!MONO_CLASS_IS_INTERFACE (klass)) {
5360 /* Imported COM Objects always derive from __ComObject. */
5362 if (MONO_CLASS_IS_IMPORT (klass)) {
5363 init_com_from_comimport (klass);
5364 if (parent == mono_defaults.object_class)
5365 parent = mono_class_get_com_object_class ();
5369 /* set the parent to something useful and safe, but mark the type as broken */
5370 parent = mono_defaults.object_class;
5371 mono_class_set_type_load_failure (klass, "");
5375 klass->parent = parent;
5377 if (mono_class_is_ginst (parent) && !parent->name) {
5379 * If the parent is a generic instance, we may get
5380 * called before it is fully initialized, especially
5381 * before it has its name.
5386 #ifndef DISABLE_REMOTING
5387 klass->marshalbyref = parent->marshalbyref;
5388 klass->contextbound = parent->contextbound;
5391 klass->delegate = parent->delegate;
5393 if (MONO_CLASS_IS_IMPORT (klass) || mono_class_is_com_object (parent))
5394 mono_class_set_is_com_object (klass);
5396 if (system_namespace) {
5397 #ifndef DISABLE_REMOTING
5398 if (klass->name [0] == 'M' && !strcmp (klass->name, "MarshalByRefObject"))
5399 klass->marshalbyref = 1;
5401 if (klass->name [0] == 'C' && !strcmp (klass->name, "ContextBoundObject"))
5402 klass->contextbound = 1;
5404 if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate"))
5405 klass->delegate = 1;
5408 if (klass->parent->enumtype || (mono_is_corlib_image (klass->parent->image) && (strcmp (klass->parent->name, "ValueType") == 0) &&
5409 (strcmp (klass->parent->name_space, "System") == 0)))
5410 klass->valuetype = 1;
5411 if (mono_is_corlib_image (klass->parent->image) && ((strcmp (klass->parent->name, "Enum") == 0) && (strcmp (klass->parent->name_space, "System") == 0))) {
5412 klass->valuetype = klass->enumtype = 1;
5414 /*klass->enumtype = klass->parent->enumtype; */
5416 /* initialize com types if COM interfaces are present */
5418 if (MONO_CLASS_IS_IMPORT (klass))
5419 init_com_from_comimport (klass);
5421 klass->parent = NULL;
5427 * mono_class_setup_supertypes:
5430 * Build the data structure needed to make fast type checks work.
5431 * This currently sets two fields in @class:
5432 * - idepth: distance between @class and System.Object in the type
5434 * - supertypes: array of classes: each element has a class in the hierarchy
5435 * starting from @class up to System.Object
5437 * LOCKING: Acquires the loader lock.
5440 mono_class_setup_supertypes (MonoClass *klass)
5443 MonoClass **supertypes;
5445 mono_atomic_load_acquire (supertypes, MonoClass **, &klass->supertypes);
5449 if (klass->parent && !klass->parent->supertypes)
5450 mono_class_setup_supertypes (klass->parent);
5452 idepth = klass->parent->idepth + 1;
5456 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, idepth);
5457 supertypes = (MonoClass **)mono_class_alloc0 (klass, sizeof (MonoClass *) * ms);
5459 if (klass->parent) {
5460 CHECKED_METADATA_WRITE_PTR ( supertypes [idepth - 1] , klass );
5463 for (supertype_idx = 0; supertype_idx < klass->parent->idepth; supertype_idx++)
5464 CHECKED_METADATA_WRITE_PTR ( supertypes [supertype_idx] , klass->parent->supertypes [supertype_idx] );
5466 CHECKED_METADATA_WRITE_PTR ( supertypes [0] , klass );
5469 mono_memory_barrier ();
5471 mono_loader_lock ();
5472 klass->idepth = idepth;
5473 /* Needed so idepth is visible before supertypes is set */
5474 mono_memory_barrier ();
5475 klass->supertypes = supertypes;
5476 mono_loader_unlock ();
5480 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5482 MonoClass *gtd = (MonoClass*)user_data;
5483 /* Only try to fix generic instances of @gtd */
5484 if (mono_class_get_generic_class (gclass)->container_class != gtd)
5487 /* Check if the generic instance has no parent. */
5488 if (gtd->parent && !gclass->parent)
5489 mono_generic_class_setup_parent (gclass, gtd);
5495 mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char *msg)
5497 mono_class_set_type_load_failure (klass, "%s", msg);
5498 mono_error_set_type_load_class (error, klass, "%s", msg);
5502 * mono_class_create_from_typedef:
5503 * @image: image where the token is valid
5504 * @type_token: typedef token
5505 * @error: used to return any error found while creating the type
5507 * Create the MonoClass* representing the specified type token.
5508 * @type_token must be a TypeDef token.
5510 * FIXME: don't return NULL on failure, just the the caller figure it out.
5513 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5515 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5516 MonoClass *klass, *parent = NULL;
5517 guint32 cols [MONO_TYPEDEF_SIZE];
5518 guint32 cols_next [MONO_TYPEDEF_SIZE];
5519 guint tidx = mono_metadata_token_index (type_token);
5520 MonoGenericContext *context = NULL;
5521 const char *name, *nspace;
5523 MonoClass **interfaces;
5524 guint32 field_last, method_last;
5525 guint32 nesting_tokeen;
5527 mono_error_init (error);
5529 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5530 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5534 mono_loader_lock ();
5536 if ((klass = (MonoClass *)mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5537 mono_loader_unlock ();
5541 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5543 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5544 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5546 if (mono_metadata_has_generic_params (image, type_token)) {
5547 klass = mono_image_alloc0 (image, sizeof (MonoClassGtd));
5548 klass->class_kind = MONO_CLASS_GTD;
5549 classes_size += sizeof (MonoClassGtd);
5552 klass = mono_image_alloc0 (image, sizeof (MonoClassDef));
5553 klass->class_kind = MONO_CLASS_DEF;
5554 classes_size += sizeof (MonoClassDef);
5559 klass->name_space = nspace;
5561 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5563 klass->image = image;
5564 klass->type_token = type_token;
5565 mono_class_set_flags (klass, cols [MONO_TYPEDEF_FLAGS]);
5567 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
5570 * Check whether we're a generic type definition.
5572 if (mono_class_is_gtd (klass)) {
5573 MonoGenericContainer *generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
5574 generic_container->owner.klass = klass;
5575 generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
5576 context = &generic_container->context;
5577 mono_class_set_generic_container (klass, generic_container);
5578 enable_gclass_recording ();
5581 if (cols [MONO_TYPEDEF_EXTENDS]) {
5583 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5585 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5586 /*WARNING: this must satisfy mono_metadata_type_hash*/
5587 klass->this_arg.byref = 1;
5588 klass->this_arg.data.klass = klass;
5589 klass->this_arg.type = MONO_TYPE_CLASS;
5590 klass->byval_arg.data.klass = klass;
5591 klass->byval_arg.type = MONO_TYPE_CLASS;
5593 parent = mono_class_get_checked (image, parent_token, error);
5594 if (parent && context) /* Always inflate */
5595 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5597 if (parent == NULL) {
5598 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5599 goto parent_failure;
5602 for (tmp = parent; tmp; tmp = tmp->parent) {
5604 mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
5605 goto parent_failure;
5607 if (mono_class_is_gtd (klass) && mono_class_is_ginst (tmp) && mono_class_get_generic_class (tmp)->container_class == klass) {
5608 mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
5609 goto parent_failure;
5614 mono_class_setup_parent (klass, parent);
5616 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5617 mono_class_setup_mono_type (klass);
5619 if (mono_class_is_gtd (klass))
5620 disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
5623 * This might access klass->byval_arg for recursion generated by generic constraints,
5624 * so it has to come after setup_mono_type ().
5626 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5627 klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5628 if (!mono_error_ok (error)) {
5629 /*FIXME implement a mono_class_set_failure_from_mono_error */
5630 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5631 mono_loader_unlock ();
5632 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5637 if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5641 if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5645 klass->cast_class = klass->element_class = klass;
5646 if (mono_is_corlib_image (klass->image)) {
5647 switch (klass->byval_arg.type) {
5649 if (mono_defaults.byte_class)
5650 klass->cast_class = mono_defaults.byte_class;
5653 if (mono_defaults.sbyte_class)
5654 mono_defaults.sbyte_class = klass;
5657 if (mono_defaults.uint16_class)
5658 mono_defaults.uint16_class = klass;
5661 if (mono_defaults.int16_class)
5662 klass->cast_class = mono_defaults.int16_class;
5665 if (mono_defaults.uint32_class)
5666 mono_defaults.uint32_class = klass;
5669 if (mono_defaults.int32_class)
5670 klass->cast_class = mono_defaults.int32_class;
5673 if (mono_defaults.uint64_class)
5674 mono_defaults.uint64_class = klass;
5677 if (mono_defaults.int64_class)
5678 klass->cast_class = mono_defaults.int64_class;
5683 if (!klass->enumtype) {
5684 if (!mono_metadata_interfaces_from_typedef_full (
5685 image, type_token, &interfaces, &icount, FALSE, context, error)){
5687 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5688 mono_loader_unlock ();
5689 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5693 /* This is required now that it is possible for more than 2^16 interfaces to exist. */
5694 g_assert(icount <= 65535);
5696 klass->interfaces = interfaces;
5697 klass->interface_count = icount;
5698 klass->interfaces_inited = 1;
5701 /*g_print ("Load class %s\n", name);*/
5704 * Compute the field and method lists
5706 int first_field_idx = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5707 mono_class_set_first_field_idx (klass, first_field_idx);
5708 int first_method_idx = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5709 mono_class_set_first_method_idx (klass, first_method_idx);
5711 if (tt->rows > tidx){
5712 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5713 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5714 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5716 field_last = image->tables [MONO_TABLE_FIELD].rows;
5717 method_last = image->tables [MONO_TABLE_METHOD].rows;
5720 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5721 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5722 mono_class_set_field_count (klass, field_last - first_field_idx);
5723 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5724 mono_class_set_method_count (klass, method_last - first_method_idx);
5726 /* reserve space to store vector pointer in arrays */
5727 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5728 klass->instance_size += 2 * sizeof (gpointer);
5729 g_assert (mono_class_get_field_count (klass) == 0);
5732 if (klass->enumtype) {
5733 MonoType *enum_basetype = mono_class_find_enum_basetype (klass, error);
5734 if (!enum_basetype) {
5735 /*set it to a default value as the whole runtime can't handle this to be null*/
5736 klass->cast_class = klass->element_class = mono_defaults.int32_class;
5737 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5738 mono_loader_unlock ();
5739 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5742 klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
5746 * If we're a generic type definition, load the constraints.
5747 * We must do this after the class has been constructed to make certain recursive scenarios
5750 if (mono_class_is_gtd (klass) && !mono_metadata_load_generic_param_constraints_checked (image, type_token, mono_class_get_generic_container (klass), error)) {
5751 mono_class_set_type_load_failure (klass, "Could not load generic parameter constrains due to %s", mono_error_get_message (error));
5752 mono_loader_unlock ();
5753 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5757 if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5758 if (!strncmp (name, "Vector", 6))
5759 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");
5760 } else if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "System.Numerics") && !strcmp (nspace, "System.Numerics")) {
5761 if (!strcmp (name, "Vector2") || !strcmp (name, "Vector3") || !strcmp (name, "Vector4"))
5762 klass->simd_type = 1;
5765 mono_loader_unlock ();
5767 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5772 mono_class_setup_mono_type (klass);
5773 mono_loader_unlock ();
5774 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5778 /** Is klass a Nullable<T> ginst? */
5780 mono_class_is_nullable (MonoClass *klass)
5782 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
5783 return gklass && gklass->container_class == mono_defaults.generic_nullable_class;
5787 /** if klass is T? return T */
5789 mono_class_get_nullable_param (MonoClass *klass)
5791 g_assert (mono_class_is_nullable (klass));
5792 return mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
5796 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5800 MonoGenericClass *gclass = mono_class_get_generic_class (klass);
5802 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5803 if (!mono_error_ok (&error)) {
5804 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5805 klass->parent = mono_defaults.object_class;
5806 mono_class_set_type_load_failure (klass, "Parent is a generic type instantiation that failed due to: %s", mono_error_get_message (&error));
5807 mono_error_cleanup (&error);
5811 mono_class_setup_parent (klass, klass->parent);
5813 if (klass->enumtype) {
5814 klass->cast_class = gtd->cast_class;
5815 klass->element_class = gtd->element_class;
5820 mono_type_is_primitive (MonoType *type)
5822 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
5823 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
5827 * Create the `MonoClass' for an instantiation of a generic type.
5828 * We only do this if we actually need it.
5831 mono_generic_class_get_class (MonoGenericClass *gclass)
5833 MonoClass *klass, *gklass;
5835 if (gclass->cached_class)
5836 return gclass->cached_class;
5838 klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClassGenericInst));
5840 gklass = gclass->container_class;
5842 if (gklass->nested_in) {
5843 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
5844 klass->nested_in = gklass->nested_in;
5847 klass->name = gklass->name;
5848 klass->name_space = gklass->name_space;
5850 klass->image = gklass->image;
5851 klass->type_token = gklass->type_token;
5853 klass->class_kind = MONO_CLASS_GINST;
5855 ((MonoClassGenericInst*)klass)->generic_class = gclass;
5857 klass->byval_arg.type = MONO_TYPE_GENERICINST;
5858 klass->this_arg.type = klass->byval_arg.type;
5859 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
5860 klass->this_arg.byref = TRUE;
5861 klass->enumtype = gklass->enumtype;
5862 klass->valuetype = gklass->valuetype;
5865 if (gklass->image->assembly_name && !strcmp (gklass->image->assembly_name, "System.Numerics.Vectors") && !strcmp (gklass->name_space, "System.Numerics") && !strcmp (gklass->name, "Vector`1")) {
5866 g_assert (gclass->context.class_inst);
5867 g_assert (gclass->context.class_inst->type_argc > 0);
5868 if (mono_type_is_primitive (gclass->context.class_inst->type_argv [0]))
5869 klass->simd_type = 1;
5871 klass->is_array_special_interface = gklass->is_array_special_interface;
5873 klass->cast_class = klass->element_class = klass;
5875 if (gclass->is_dynamic) {
5877 * 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.
5878 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
5879 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
5881 if (!gklass->wastypebuilder)
5884 if (klass->enumtype) {
5886 * For enums, gklass->fields might not been set, but instance_size etc. is
5887 * already set in mono_reflection_create_internal_class (). For non-enums,
5888 * these will be computed normally in mono_class_layout_fields ().
5890 klass->instance_size = gklass->instance_size;
5891 klass->sizes.class_size = gklass->sizes.class_size;
5892 klass->size_inited = 1;
5896 mono_loader_lock ();
5898 if (gclass->cached_class) {
5899 mono_loader_unlock ();
5900 return gclass->cached_class;
5903 if (record_gclass_instantiation > 0)
5904 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
5906 if (mono_class_is_nullable (klass))
5907 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
5909 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5911 mono_generic_class_setup_parent (klass, gklass);
5913 if (gclass->is_dynamic)
5914 mono_class_setup_supertypes (klass);
5916 mono_memory_barrier ();
5917 gclass->cached_class = klass;
5919 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5921 ++class_ginst_count;
5922 inflated_classes_size += sizeof (MonoClassGenericInst);
5924 mono_loader_unlock ();
5930 get_image_for_container (MonoGenericContainer *container)
5933 if (container->is_anonymous) {
5934 result = container->owner.image;
5937 if (container->is_method) {
5938 MonoMethod *method = container->owner.method;
5939 g_assert_checked (method);
5940 klass = method->klass;
5942 klass = container->owner.klass;
5944 g_assert_checked (klass);
5945 result = klass->image;
5952 get_image_for_generic_param (MonoGenericParam *param)
5954 MonoGenericContainer *container = mono_generic_param_owner (param);
5955 g_assert_checked (container);
5956 return get_image_for_container (container);
5959 // Make a string in the designated image consisting of a single integer.
5960 #define INT_STRING_SIZE 16
5962 make_generic_name_string (MonoImage *image, int num)
5964 char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
5965 g_snprintf (name, INT_STRING_SIZE, "%d", num);
5969 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
5970 // pinfo is derived from param by the caller for us.
5972 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
5974 MonoClass *klass, **ptr;
5976 MonoGenericContainer *container = mono_generic_param_owner (param);
5977 g_assert_checked (container);
5979 MonoImage *image = get_image_for_container (container);
5980 gboolean is_mvar = container->is_method;
5981 gboolean is_anonymous = container->is_anonymous;
5983 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassGenericParam));
5984 klass->class_kind = MONO_CLASS_GPARAM;
5985 classes_size += sizeof (MonoClassGenericParam);
5986 ++class_gparam_count;
5989 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
5991 int n = mono_generic_param_num (param);
5992 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
5996 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , "" );
5997 } else if (is_mvar) {
5998 MonoMethod *omethod = container->owner.method;
5999 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
6001 MonoClass *oklass = container->owner.klass;
6002 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
6005 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6007 // Count non-NULL items in pinfo->constraints
6010 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6014 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6015 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
6017 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
6018 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
6020 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
6023 if (count - pos > 0) {
6024 klass->interface_count = count - pos;
6025 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
6026 klass->interfaces_inited = TRUE;
6027 for (i = pos; i < count; i++)
6028 CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
6031 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
6033 klass->inited = TRUE;
6034 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class , klass );
6035 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
6037 klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6038 klass->this_arg.type = klass->byval_arg.type;
6039 CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param , param );
6040 CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
6041 klass->this_arg.byref = TRUE;
6043 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6044 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6046 /*Init these fields to sane values*/
6047 klass->min_align = 1;
6049 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6050 * constrained to, the JIT depends on this.
6052 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6053 mono_memory_barrier ();
6054 klass->size_inited = 1;
6056 mono_class_setup_supertypes (klass);
6058 if (count - pos > 0) {
6059 mono_class_setup_vtable (klass->parent);
6060 if (mono_class_has_failure (klass->parent))
6061 mono_class_set_type_load_failure (klass, "Failed to setup parent interfaces");
6063 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6069 #define FAST_CACHE_SIZE 16
6072 * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6073 * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6074 * we cache the MonoClasses.
6075 * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6076 * LOCKING: Takes the image lock depending on @take_lock.
6079 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6081 int n = mono_generic_param_num (param);
6082 MonoImage *image = get_image_for_generic_param (param);
6083 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6084 MonoClass *klass = NULL;
6089 // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6090 // For high numbers or constraints we have to use pointer hashes.
6091 if (param->gshared_constraint) {
6092 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6095 mono_image_lock (image);
6096 klass = (MonoClass *)g_hash_table_lookup (ht, param);
6098 mono_image_unlock (image);
6103 if (n < FAST_CACHE_SIZE) {
6105 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6107 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6109 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6112 mono_image_lock (image);
6113 klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6115 mono_image_unlock (image);
6122 * LOCKING: Image lock (param->image) must be held
6125 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6127 int n = mono_generic_param_num (param);
6128 MonoImage *image = get_image_for_generic_param (param);
6129 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6133 if (param->gshared_constraint) {
6134 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6136 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6137 mono_memory_barrier ();
6139 image->mvar_cache_constrained = ht;
6141 image->var_cache_constrained = ht;
6143 g_hash_table_insert (ht, param, klass);
6144 } else if (n < FAST_CACHE_SIZE) {
6146 /* Requires locking to avoid droping an already published class */
6147 if (!image->mvar_cache_fast)
6148 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6149 image->mvar_cache_fast [n] = klass;
6151 if (!image->var_cache_fast)
6152 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6153 image->var_cache_fast [n] = klass;
6156 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6158 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6160 ht = g_hash_table_new (NULL, NULL);
6161 mono_memory_barrier ();
6163 image->mvar_cache_slow = ht;
6165 image->var_cache_slow = ht;
6168 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6173 * LOCKING: Acquires the image lock (@image).
6176 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6178 MonoImage *image = get_image_for_generic_param (param);
6179 MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6180 MonoClass *klass, *klass2;
6182 // If a klass already exists for this object and is cached, return it.
6183 if (pinfo) // Non-anonymous
6184 klass = pinfo->pklass;
6186 klass = get_anon_gparam_class (param, TRUE);
6191 // Create a new klass
6192 klass = make_generic_param_class (param, pinfo);
6194 // Now we need to cache the klass we created.
6195 // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6196 // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6197 // and allow our newly-created klass object to just leak.
6198 mono_memory_barrier ();
6200 mono_image_lock (image);
6202 // Here "klass2" refers to the klass potentially created by the other thread.
6203 if (pinfo) // Repeat check from above
6204 klass2 = pinfo->pklass;
6206 klass2 = get_anon_gparam_class (param, FALSE);
6213 pinfo->pklass = klass;
6215 set_anon_gparam_class (param, klass);
6217 mono_image_unlock (image);
6219 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6221 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED); // Alert profiler about botched class create
6223 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6229 * mono_class_from_generic_parameter:
6230 * @param: Parameter to find/construct a class for.
6231 * @arg2: Is ignored.
6232 * @arg3: Is ignored.
6235 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6237 return mono_class_from_generic_parameter_internal (param);
6241 mono_ptr_class_get (MonoType *type)
6244 MonoClass *el_class;
6248 el_class = mono_class_from_mono_type (type);
6249 image = el_class->image;
6251 mono_image_lock (image);
6252 if (image->ptr_cache) {
6253 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6254 mono_image_unlock (image);
6258 mono_image_unlock (image);
6260 result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassPointer));
6262 classes_size += sizeof (MonoClassPointer);
6263 ++class_pointer_count;
6265 result->parent = NULL; /* no parent for PTR types */
6266 result->name_space = el_class->name_space;
6267 name = g_strdup_printf ("%s*", el_class->name);
6268 result->name = mono_image_strdup (image, name);
6269 result->class_kind = MONO_CLASS_POINTER;
6272 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6274 result->image = el_class->image;
6275 result->inited = TRUE;
6276 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6277 result->cast_class = result->element_class = el_class;
6278 result->blittable = TRUE;
6280 result->byval_arg.type = MONO_TYPE_PTR;
6281 result->this_arg.type = result->byval_arg.type;
6282 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6283 result->this_arg.byref = TRUE;
6285 mono_class_setup_supertypes (result);
6287 mono_image_lock (image);
6288 if (image->ptr_cache) {
6290 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6291 mono_image_unlock (image);
6292 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6296 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6298 g_hash_table_insert (image->ptr_cache, el_class, result);
6299 mono_image_unlock (image);
6301 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6307 mono_fnptr_class_get (MonoMethodSignature *sig)
6309 MonoClass *result, *cached;
6310 static GHashTable *ptr_hash = NULL;
6312 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6314 mono_loader_lock ();
6316 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6317 cached = (MonoClass *)g_hash_table_lookup (ptr_hash, sig);
6318 mono_loader_unlock ();
6322 result = g_new0 (MonoClass, 1);
6324 result->parent = NULL; /* no parent for PTR types */
6325 result->name_space = "System";
6326 result->name = "MonoFNPtrFakeClass";
6327 result->class_kind = MONO_CLASS_POINTER;
6329 result->image = mono_defaults.corlib; /* need to fix... */
6330 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6331 result->cast_class = result->element_class = result;
6332 result->byval_arg.type = MONO_TYPE_FNPTR;
6333 result->this_arg.type = result->byval_arg.type;
6334 result->this_arg.data.method = result->byval_arg.data.method = sig;
6335 result->this_arg.byref = TRUE;
6336 result->blittable = TRUE;
6337 result->inited = TRUE;
6339 mono_class_setup_supertypes (result);
6341 mono_loader_lock ();
6343 cached = (MonoClass *)g_hash_table_lookup (ptr_hash, sig);
6346 mono_loader_unlock ();
6350 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6352 classes_size += sizeof (MonoClassPointer);
6353 ++class_pointer_count;
6355 g_hash_table_insert (ptr_hash, sig, result);
6357 mono_loader_unlock ();
6359 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6365 * mono_class_from_mono_type:
6366 * @type: describes the type to return
6368 * This returns a MonoClass for the specified MonoType, the value is never NULL.
6371 mono_class_from_mono_type (MonoType *type)
6373 switch (type->type) {
6374 case MONO_TYPE_OBJECT:
6375 return type->data.klass? type->data.klass: mono_defaults.object_class;
6376 case MONO_TYPE_VOID:
6377 return type->data.klass? type->data.klass: mono_defaults.void_class;
6378 case MONO_TYPE_BOOLEAN:
6379 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6380 case MONO_TYPE_CHAR:
6381 return type->data.klass? type->data.klass: mono_defaults.char_class;
6383 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6385 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6387 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6389 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6391 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6393 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6395 return type->data.klass? type->data.klass: mono_defaults.int_class;
6397 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6399 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6401 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6403 return type->data.klass? type->data.klass: mono_defaults.single_class;
6405 return type->data.klass? type->data.klass: mono_defaults.double_class;
6406 case MONO_TYPE_STRING:
6407 return type->data.klass? type->data.klass: mono_defaults.string_class;
6408 case MONO_TYPE_TYPEDBYREF:
6409 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6410 case MONO_TYPE_ARRAY:
6411 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6413 return mono_ptr_class_get (type->data.type);
6414 case MONO_TYPE_FNPTR:
6415 return mono_fnptr_class_get (type->data.method);
6416 case MONO_TYPE_SZARRAY:
6417 return mono_array_class_get (type->data.klass, 1);
6418 case MONO_TYPE_CLASS:
6419 case MONO_TYPE_VALUETYPE:
6420 return type->data.klass;
6421 case MONO_TYPE_GENERICINST:
6422 return mono_generic_class_get_class (type->data.generic_class);
6423 case MONO_TYPE_MVAR:
6425 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6427 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6428 g_assert_not_reached ();
6431 // Yes, this returns NULL, even if it is documented as not doing so, but there
6432 // is no way for the code to make it this far, due to the assert above.
6437 * mono_type_retrieve_from_typespec
6438 * @image: context where the image is created
6439 * @type_spec: typespec token
6440 * @context: the generic context used to evaluate generic instantiations in
6443 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6445 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6447 *did_inflate = FALSE;
6452 if (context && (context->class_inst || context->method_inst)) {
6453 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6455 if (!mono_error_ok (error)) {
6461 *did_inflate = TRUE;
6468 * mono_class_create_from_typespec
6469 * @image: context where the image is created
6470 * @type_spec: typespec token
6471 * @context: the generic context used to evaluate generic instantiations in
6474 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6477 gboolean inflated = FALSE;
6478 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6479 return_val_if_nok (error, NULL);
6480 ret = mono_class_from_mono_type (t);
6482 mono_metadata_free_type (t);
6487 * mono_bounded_array_class_get:
6488 * @element_class: element class
6489 * @rank: the dimension of the array class
6490 * @bounded: whenever the array has non-zero bounds
6492 * Returns: A class object describing the array with element type @element_type and
6496 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6499 MonoClass *klass, *cached, *k;
6500 MonoClass *parent = NULL;
6501 GSList *list, *rootlist = NULL;
6505 g_assert (rank <= 255);
6508 /* bounded only matters for one-dimensional arrays */
6511 image = eclass->image;
6515 if (rank == 1 && !bounded) {
6517 * This case is very frequent not just during compilation because of calls
6518 * from mono_class_from_mono_type (), mono_array_new (),
6519 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6521 mono_os_mutex_lock (&image->szarray_cache_lock);
6522 if (!image->szarray_cache)
6523 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6524 cached = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6525 mono_os_mutex_unlock (&image->szarray_cache_lock);
6527 mono_loader_lock ();
6528 if (!image->array_cache)
6529 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6530 rootlist = (GSList *)g_hash_table_lookup (image->array_cache, eclass);
6531 for (list = rootlist; list; list = list->next) {
6532 k = (MonoClass *)list->data;
6533 if ((k->rank == rank) && (k->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6538 mono_loader_unlock ();
6543 parent = mono_defaults.array_class;
6544 if (!parent->inited)
6545 mono_class_init (parent);
6547 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassArray));
6549 klass->image = image;
6550 klass->name_space = eclass->name_space;
6551 klass->class_kind = MONO_CLASS_ARRAY;
6553 nsize = strlen (eclass->name);
6554 name = (char *)g_malloc (nsize + 2 + rank + 1);
6555 memcpy (name, eclass->name, nsize);
6558 memset (name + nsize + 1, ',', rank - 1);
6560 name [nsize + rank] = '*';
6561 name [nsize + rank + bounded] = ']';
6562 name [nsize + rank + bounded + 1] = 0;
6563 klass->name = mono_image_strdup (image, name);
6566 klass->type_token = 0;
6567 klass->parent = parent;
6568 klass->instance_size = mono_class_instance_size (klass->parent);
6570 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6571 /*Arrays of those two types are invalid.*/
6572 MonoError prepared_error;
6573 mono_error_init (&prepared_error);
6574 mono_error_set_invalid_program (&prepared_error, "Arrays of void or System.TypedReference types are invalid.");
6575 mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6576 mono_error_cleanup (&prepared_error);
6577 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6578 guint32 ref_info_handle = mono_class_get_ref_info_handle (eclass);
6579 if (!ref_info_handle || eclass->wastypebuilder) {
6580 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6581 g_assert (ref_info_handle && !eclass->wastypebuilder);
6583 /* element_size -1 is ok as this is not an instantitable type*/
6584 klass->sizes.element_size = -1;
6586 klass->sizes.element_size = mono_class_array_element_size (eclass);
6588 mono_class_setup_supertypes (klass);
6590 if (mono_class_is_ginst (eclass))
6591 mono_class_init (eclass);
6592 if (!eclass->size_inited)
6593 mono_class_setup_fields (eclass);
6594 mono_class_set_type_load_failure_causedby_class (klass, eclass, "Could not load array element type");
6595 /*FIXME we fail the array type, but we have to let other fields be set.*/
6597 klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6601 if (eclass->enumtype)
6602 klass->cast_class = eclass->element_class;
6604 klass->cast_class = eclass;
6606 switch (klass->cast_class->byval_arg.type) {
6608 klass->cast_class = mono_defaults.byte_class;
6611 klass->cast_class = mono_defaults.int16_class;
6614 #if SIZEOF_VOID_P == 4
6618 klass->cast_class = mono_defaults.int32_class;
6621 #if SIZEOF_VOID_P == 8
6625 klass->cast_class = mono_defaults.int64_class;
6631 klass->element_class = eclass;
6633 if ((rank > 1) || bounded) {
6634 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6635 klass->byval_arg.type = MONO_TYPE_ARRAY;
6636 klass->byval_arg.data.array = at;
6637 at->eklass = eclass;
6639 /* FIXME: complete.... */
6641 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6642 klass->byval_arg.data.klass = eclass;
6644 klass->this_arg = klass->byval_arg;
6645 klass->this_arg.byref = 1;
6647 mono_loader_lock ();
6649 /* Check cache again */
6651 if (rank == 1 && !bounded) {
6652 mono_os_mutex_lock (&image->szarray_cache_lock);
6653 cached = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6654 mono_os_mutex_unlock (&image->szarray_cache_lock);
6656 rootlist = (GSList *)g_hash_table_lookup (image->array_cache, eclass);
6657 for (list = rootlist; list; list = list->next) {
6658 k = (MonoClass *)list->data;
6659 if ((k->rank == rank) && (k->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6666 mono_loader_unlock ();
6670 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6672 classes_size += sizeof (MonoClassArray);
6673 ++class_array_count;
6675 if (rank == 1 && !bounded) {
6676 mono_os_mutex_lock (&image->szarray_cache_lock);
6677 g_hash_table_insert (image->szarray_cache, eclass, klass);
6678 mono_os_mutex_unlock (&image->szarray_cache_lock);
6680 list = g_slist_append (rootlist, klass);
6681 g_hash_table_insert (image->array_cache, eclass, list);
6684 mono_loader_unlock ();
6686 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6692 * mono_array_class_get:
6693 * @element_class: element class
6694 * @rank: the dimension of the array class
6696 * Returns: A class object describing the array with element type @element_type and
6700 mono_array_class_get (MonoClass *eclass, guint32 rank)
6702 return mono_bounded_array_class_get (eclass, rank, FALSE);
6706 * mono_class_instance_size:
6709 * Use to get the size of a class in bytes.
6711 * Returns: The size of an object instance
6714 mono_class_instance_size (MonoClass *klass)
6716 if (!klass->size_inited)
6717 mono_class_init (klass);
6719 return klass->instance_size;
6723 * mono_class_min_align:
6726 * Use to get the computed minimum alignment requirements for the specified class.
6728 * Returns: minimum alignment requirements
6731 mono_class_min_align (MonoClass *klass)
6733 if (!klass->size_inited)
6734 mono_class_init (klass);
6736 return klass->min_align;
6740 * mono_class_value_size:
6743 * This function is used for value types, and return the
6744 * space and the alignment to store that kind of value object.
6746 * Returns: the size of a value of kind @klass
6749 mono_class_value_size (MonoClass *klass, guint32 *align)
6753 /* fixme: check disable, because we still have external revereces to
6754 * mscorlib and Dummy Objects
6756 /*g_assert (klass->valuetype);*/
6758 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6761 *align = klass->min_align;
6767 * mono_class_data_size:
6770 * Returns: The size of the static class data
6773 mono_class_data_size (MonoClass *klass)
6776 mono_class_init (klass);
6777 /* This can happen with dynamically created types */
6778 if (!klass->fields_inited)
6779 mono_class_setup_fields (klass);
6781 /* in arrays, sizes.class_size is unioned with element_size
6782 * and arrays have no static fields
6786 return klass->sizes.class_size;
6790 * Auxiliary routine to mono_class_get_field
6792 * Takes a field index instead of a field token.
6794 static MonoClassField *
6795 mono_class_get_field_idx (MonoClass *klass, int idx)
6797 mono_class_setup_fields (klass);
6798 if (mono_class_has_failure (klass))
6802 int first_field_idx = mono_class_get_first_field_idx (klass);
6803 int fcount = mono_class_get_field_count (klass);
6804 if (klass->image->uncompressed_metadata) {
6806 * first_field_idx points to the FieldPtr table, while idx points into the
6807 * Field table, so we have to do a search.
6809 /*FIXME this is broken for types with multiple fields with the same name.*/
6810 const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6813 for (i = 0; i < fcount; ++i)
6814 if (mono_field_get_name (&klass->fields [i]) == name)
6815 return &klass->fields [i];
6816 g_assert_not_reached ();
6819 if ((idx >= first_field_idx) && (idx < first_field_idx + fcount)){
6820 return &klass->fields [idx - first_field_idx];
6824 klass = klass->parent;
6830 * mono_class_get_field:
6831 * @class: the class to lookup the field.
6832 * @field_token: the field token
6834 * Returns: A MonoClassField representing the type and offset of
6835 * the field, or a NULL value if the field does not belong to this
6839 mono_class_get_field (MonoClass *klass, guint32 field_token)
6841 int idx = mono_metadata_token_index (field_token);
6843 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6845 return mono_class_get_field_idx (klass, idx - 1);
6849 * mono_class_get_field_from_name:
6850 * @klass: the class to lookup the field.
6851 * @name: the field name
6853 * Search the class @klass and it's parents for a field with the name @name.
6855 * Returns: The MonoClassField pointer of the named field or NULL
6858 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6860 return mono_class_get_field_from_name_full (klass, name, NULL);
6864 * mono_class_get_field_from_name_full:
6865 * @klass: the class to lookup the field.
6866 * @name: the field name
6867 * @type: the type of the fields. This optional.
6869 * Search the class @klass and it's parents for a field with the name @name and type @type.
6871 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
6872 * of its generic type definition.
6874 * Returns: The MonoClassField pointer of the named field or NULL
6877 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6881 mono_class_setup_fields (klass);
6882 if (mono_class_has_failure (klass))
6886 int fcount = mono_class_get_field_count (klass);
6887 for (i = 0; i < fcount; ++i) {
6888 MonoClassField *field = &klass->fields [i];
6890 if (strcmp (name, mono_field_get_name (field)) != 0)
6894 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6895 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6900 klass = klass->parent;
6906 * mono_class_get_field_token:
6907 * @field: the field we need the token of
6909 * Get the token of a field. Note that the tokesn is only valid for the image
6910 * the field was loaded from. Don't use this function for fields in dynamic types.
6912 * Returns: The token representing the field in the image it was loaded from.
6915 mono_class_get_field_token (MonoClassField *field)
6917 MonoClass *klass = field->parent;
6920 mono_class_setup_fields (klass);
6925 int first_field_idx = mono_class_get_first_field_idx (klass);
6926 int fcount = mono_class_get_field_count (klass);
6927 for (i = 0; i < fcount; ++i) {
6928 if (&klass->fields [i] == field) {
6929 int idx = first_field_idx + i + 1;
6931 if (klass->image->uncompressed_metadata)
6932 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
6933 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
6936 klass = klass->parent;
6939 g_assert_not_reached ();
6944 mono_field_get_index (MonoClassField *field)
6946 int index = field - field->parent->fields;
6947 g_assert (index >= 0 && index < mono_class_get_field_count (field->parent));
6953 * mono_class_get_field_default_value:
6955 * Return the default value of the field as a pointer into the metadata blob.
6958 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
6961 guint32 constant_cols [MONO_CONSTANT_SIZE];
6963 MonoClass *klass = field->parent;
6964 MonoFieldDefaultValue *def_values;
6966 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
6968 def_values = mono_class_get_field_def_values (klass);
6970 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
6972 mono_class_set_field_def_values (klass, def_values);
6975 field_index = mono_field_get_index (field);
6977 if (!def_values [field_index].data) {
6978 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
6982 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
6984 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
6985 def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
6986 mono_memory_barrier ();
6987 def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
6990 *def_type = def_values [field_index].def_type;
6991 return def_values [field_index].data;
6995 mono_property_get_index (MonoProperty *prop)
6997 MonoClassPropertyInfo *info = mono_class_get_property_info (prop->parent);
6998 int index = prop - info->properties;
7000 g_assert (index >= 0 && index < info->count);
7006 * mono_class_get_property_default_value:
7008 * Return the default value of the field as a pointer into the metadata blob.
7011 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7014 guint32 constant_cols [MONO_CONSTANT_SIZE];
7015 MonoClass *klass = property->parent;
7017 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7019 * We don't cache here because it is not used by C# so it's quite rare, but
7020 * we still do the lookup in klass->ext because that is where the data
7021 * is stored for dynamic assemblies.
7024 if (image_is_dynamic (klass->image)) {
7025 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
7026 int prop_index = mono_property_get_index (property);
7027 if (info->def_values && info->def_values [prop_index].data) {
7028 *def_type = info->def_values [prop_index].def_type;
7029 return info->def_values [prop_index].data;
7033 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7037 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7038 *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7039 return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7043 mono_class_get_event_token (MonoEvent *event)
7045 MonoClass *klass = event->parent;
7049 MonoClassEventInfo *info = mono_class_get_event_info (klass);
7051 for (i = 0; i < info->count; ++i) {
7052 if (&info->events [i] == event)
7053 return mono_metadata_make_token (MONO_TABLE_EVENT, info->first + i + 1);
7056 klass = klass->parent;
7059 g_assert_not_reached ();
7064 * mono_class_get_property_from_name:
7066 * @name: name of the property to lookup in the specified class
7068 * Use this method to lookup a property in a class
7069 * Returns: the MonoProperty with the given name, or NULL if the property
7070 * does not exist on the @klass.
7073 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7077 gpointer iter = NULL;
7078 while ((p = mono_class_get_properties (klass, &iter))) {
7079 if (! strcmp (name, p->name))
7082 klass = klass->parent;
7088 * mono_class_get_property_token:
7089 * @prop: MonoProperty to query
7091 * Returns: The ECMA token for the specified property.
7094 mono_class_get_property_token (MonoProperty *prop)
7096 MonoClass *klass = prop->parent;
7100 gpointer iter = NULL;
7101 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
7102 while ((p = mono_class_get_properties (klass, &iter))) {
7103 if (&info->properties [i] == prop)
7104 return mono_metadata_make_token (MONO_TABLE_PROPERTY, info->first + i + 1);
7108 klass = klass->parent;
7111 g_assert_not_reached ();
7116 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7118 const char *name, *nspace;
7119 if (image_is_dynamic (image))
7120 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7122 switch (type_token & 0xff000000){
7123 case MONO_TOKEN_TYPE_DEF: {
7124 guint32 cols [MONO_TYPEDEF_SIZE];
7125 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7126 guint tidx = mono_metadata_token_index (type_token);
7128 if (tidx > tt->rows)
7129 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7131 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7132 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7133 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7134 if (strlen (nspace) == 0)
7135 return g_strdup_printf ("%s", name);
7137 return g_strdup_printf ("%s.%s", nspace, name);
7140 case MONO_TOKEN_TYPE_REF: {
7142 guint32 cols [MONO_TYPEREF_SIZE];
7143 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7144 guint tidx = mono_metadata_token_index (type_token);
7147 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7149 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7150 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7151 mono_error_cleanup (&error);
7155 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7156 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7157 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7158 if (strlen (nspace) == 0)
7159 return g_strdup_printf ("%s", name);
7161 return g_strdup_printf ("%s.%s", nspace, name);
7164 case MONO_TOKEN_TYPE_SPEC:
7165 return g_strdup_printf ("Typespec 0x%08x", type_token);
7167 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7172 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7174 if (image_is_dynamic (image))
7175 return g_strdup_printf ("DynamicAssembly %s", image->name);
7177 switch (type_token & 0xff000000){
7178 case MONO_TOKEN_TYPE_DEF:
7179 if (image->assembly)
7180 return mono_stringify_assembly_name (&image->assembly->aname);
7181 else if (image->assembly_name)
7182 return g_strdup (image->assembly_name);
7183 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7184 case MONO_TOKEN_TYPE_REF: {
7186 MonoAssemblyName aname;
7187 guint32 cols [MONO_TYPEREF_SIZE];
7188 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7189 guint32 idx = mono_metadata_token_index (type_token);
7192 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7194 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7195 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7196 mono_error_cleanup (&error);
7199 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7201 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7202 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7203 case MONO_RESOLUTION_SCOPE_MODULE:
7205 return g_strdup ("");
7206 case MONO_RESOLUTION_SCOPE_MODULEREF:
7208 return g_strdup ("");
7209 case MONO_RESOLUTION_SCOPE_TYPEREF:
7211 return g_strdup ("");
7212 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7213 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7214 return mono_stringify_assembly_name (&aname);
7216 g_assert_not_reached ();
7220 case MONO_TOKEN_TYPE_SPEC:
7222 return g_strdup ("");
7224 g_assert_not_reached ();
7231 * mono_class_get_full:
7232 * @image: the image where the class resides
7233 * @type_token: the token for the class
7234 * @context: the generic context used to evaluate generic instantiations in
7235 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7237 * Returns: The MonoClass that represents @type_token in @image
7240 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7244 klass = mono_class_get_checked (image, type_token, &error);
7246 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7247 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7249 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7255 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7259 mono_error_init (error);
7260 klass = mono_class_get_checked (image, type_token, error);
7262 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7263 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7268 * mono_class_get_checked:
7269 * @image: the image where the class resides
7270 * @type_token: the token for the class
7271 * @error: error object to return any error
7273 * Returns: The MonoClass that represents @type_token in @image, or NULL on error.
7276 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7278 MonoClass *klass = NULL;
7280 mono_error_init (error);
7282 if (image_is_dynamic (image)) {
7283 int table = mono_metadata_token_table (type_token);
7285 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7286 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7289 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
7293 switch (type_token & 0xff000000){
7294 case MONO_TOKEN_TYPE_DEF:
7295 klass = mono_class_create_from_typedef (image, type_token, error);
7297 case MONO_TOKEN_TYPE_REF:
7298 klass = mono_class_from_typeref_checked (image, type_token, error);
7300 case MONO_TOKEN_TYPE_SPEC:
7301 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7304 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7308 /* Generic case, should be avoided for when a better error is possible. */
7309 if (!klass && mono_error_ok (error)) {
7310 char *name = mono_class_name_from_token (image, type_token);
7311 char *assembly = mono_assembly_name_from_token (image, type_token);
7312 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7320 * mono_type_get_checked:
7321 * @image: the image where the type resides
7322 * @type_token: the token for the type
7323 * @context: the generic context used to evaluate generic instantiations in
7324 * @error: Error handling context
7326 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7328 * Returns: The MonoType that represents @type_token in @image
7331 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7333 MonoType *type = NULL;
7334 gboolean inflated = FALSE;
7336 mono_error_init (error);
7338 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7339 if (image_is_dynamic (image)) {
7340 MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
7341 return_val_if_nok (error, NULL);
7342 return mono_class_get_type (klass);
7345 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7346 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7353 return mono_class_get_type (klass);
7356 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7363 MonoType *tmp = type;
7364 type = mono_class_get_type (mono_class_from_mono_type (type));
7365 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7366 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7367 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7369 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7371 if (type->type != tmp->type)
7374 mono_metadata_free_type (tmp);
7381 * @image: image where the class token will be looked up.
7382 * @type_token: a type token from the image
7384 * Returns the MonoClass with the given @type_token on the @image
7387 mono_class_get (MonoImage *image, guint32 type_token)
7389 return mono_class_get_full (image, type_token, NULL);
7393 * mono_image_init_name_cache:
7395 * Initializes the class name cache stored in image->name_cache.
7397 * LOCKING: Acquires the corresponding image lock.
7400 mono_image_init_name_cache (MonoImage *image)
7402 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7403 guint32 cols [MONO_TYPEDEF_SIZE];
7406 guint32 i, visib, nspace_index;
7407 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7409 if (image->name_cache)
7412 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7414 if (image_is_dynamic (image)) {
7415 mono_image_lock (image);
7416 if (image->name_cache) {
7417 /* Somebody initialized it before us */
7418 g_hash_table_destroy (the_name_cache);
7420 mono_atomic_store_release (&image->name_cache, the_name_cache);
7422 mono_image_unlock (image);
7426 /* Temporary hash table to avoid lookups in the nspace_table */
7427 name_cache2 = g_hash_table_new (NULL, NULL);
7429 for (i = 1; i <= t->rows; ++i) {
7430 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7431 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7433 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7434 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7436 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7438 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7439 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7441 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7442 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7443 if (!nspace_table) {
7444 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7445 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7446 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7449 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7452 /* Load type names from EXPORTEDTYPES table */
7454 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7455 guint32 cols [MONO_EXP_TYPE_SIZE];
7458 for (i = 0; i < t->rows; ++i) {
7459 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7461 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7462 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7466 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7467 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7469 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7470 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7471 if (!nspace_table) {
7472 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7473 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7474 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7477 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7481 g_hash_table_destroy (name_cache2);
7483 mono_image_lock (image);
7484 if (image->name_cache) {
7485 /* Somebody initialized it before us */
7486 g_hash_table_destroy (the_name_cache);
7488 mono_atomic_store_release (&image->name_cache, the_name_cache);
7490 mono_image_unlock (image);
7493 /*FIXME Only dynamic assemblies should allow this operation.*/
7495 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7496 const char *name, guint32 index)
7498 GHashTable *nspace_table;
7499 GHashTable *name_cache;
7502 mono_image_init_name_cache (image);
7503 mono_image_lock (image);
7505 name_cache = image->name_cache;
7506 if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7507 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7508 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7511 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7512 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7514 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7516 mono_image_unlock (image);
7525 find_nocase (gpointer key, gpointer value, gpointer user_data)
7527 char *name = (char*)key;
7528 FindUserData *data = (FindUserData*)user_data;
7530 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7531 data->value = value;
7535 * mono_class_from_name_case:
7536 * @image: The MonoImage where the type is looked up in
7537 * @name_space: the type namespace
7538 * @name: the type short name.
7539 * @deprecated: use the mono_class_from_name_case_checked variant instead.
7541 * Obtains a MonoClass with a given namespace and a given name which
7542 * is located in the given MonoImage. The namespace and name
7543 * lookups are case insensitive.
7546 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7549 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7550 mono_error_cleanup (&error);
7556 * mono_class_from_name_case:
7557 * @image: The MonoImage where the type is looked up in
7558 * @name_space: the type namespace
7559 * @name: the type short name.
7562 * Obtains a MonoClass with a given namespace and a given name which
7563 * is located in the given MonoImage. The namespace and name
7564 * lookups are case insensitive.
7566 * Returns: The MonoClass if the given namespace and name were found, or NULL if it
7567 * was not found. The @error object will contain information about the problem
7571 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7573 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7574 guint32 cols [MONO_TYPEDEF_SIZE];
7579 mono_error_init (error);
7581 if (image_is_dynamic (image)) {
7583 FindUserData user_data;
7585 mono_image_init_name_cache (image);
7586 mono_image_lock (image);
7588 user_data.key = name_space;
7589 user_data.value = NULL;
7590 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7592 if (user_data.value) {
7593 GHashTable *nspace_table = (GHashTable*)user_data.value;
7595 user_data.key = name;
7596 user_data.value = NULL;
7598 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7600 if (user_data.value)
7601 token = GPOINTER_TO_UINT (user_data.value);
7604 mono_image_unlock (image);
7607 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7613 /* add a cache if needed */
7614 for (i = 1; i <= t->rows; ++i) {
7615 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7616 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7618 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7619 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7621 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7623 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7624 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7625 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7626 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7632 return_nested_in (MonoClass *klass, char *nested)
7635 char *s = strchr (nested, '/');
7636 gpointer iter = NULL;
7643 while ((found = mono_class_get_nested_types (klass, &iter))) {
7644 if (strcmp (found->name, nested) == 0) {
7646 return return_nested_in (found, s);
7654 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7656 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7657 MonoImage *file_image;
7661 mono_error_init (error);
7664 * The EXPORTEDTYPES table only contains public types, so have to search the
7666 * Note: image->modules contains the contents of the MODULEREF table, while
7667 * the real module list is in the FILE table.
7669 for (i = 0; i < file_table->rows; i++) {
7670 guint32 cols [MONO_FILE_SIZE];
7671 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7672 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7675 file_image = mono_image_load_file_for_image_checked (image, i + 1, error);
7677 klass = mono_class_from_name_checked (file_image, name_space, name, error);
7678 if (klass || !is_ok (error))
7687 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7689 GHashTable *nspace_table;
7690 MonoImage *loaded_image;
7697 mono_error_init (error);
7699 // Checking visited images avoids stack overflows when cyclic references exist.
7700 if (g_hash_table_lookup (visited_images, image))
7703 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7705 if ((nested = strchr (name, '/'))) {
7706 int pos = nested - name;
7707 int len = strlen (name);
7710 memcpy (buf, name, len + 1);
7712 nested = buf + pos + 1;
7716 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7717 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7718 gboolean res = get_class_from_name (image, name_space, name, &klass);
7721 klass = search_modules (image, name_space, name, error);
7726 return klass ? return_nested_in (klass, nested) : NULL;
7732 mono_image_init_name_cache (image);
7733 mono_image_lock (image);
7735 nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7738 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7740 mono_image_unlock (image);
7742 if (!token && image_is_dynamic (image) && image->modules) {
7743 /* Search modules as well */
7744 for (i = 0; i < image->module_count; ++i) {
7745 MonoImage *module = image->modules [i];
7747 klass = mono_class_from_name_checked (module, name_space, name, error);
7748 if (klass || !is_ok (error))
7754 klass = search_modules (image, name_space, name, error);
7755 if (klass || !is_ok (error))
7760 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7761 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7762 guint32 cols [MONO_EXP_TYPE_SIZE];
7765 idx = mono_metadata_token_index (token);
7767 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7769 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7770 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7771 loaded_image = mono_assembly_load_module_checked (image->assembly, impl >> MONO_IMPLEMENTATION_BITS, error);
7774 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7776 return klass ? return_nested_in (klass, nested) : NULL;
7778 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7779 guint32 assembly_idx;
7781 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7783 mono_assembly_load_reference (image, assembly_idx - 1);
7784 g_assert (image->references [assembly_idx - 1]);
7785 if (image->references [assembly_idx - 1] == (gpointer)-1)
7787 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
7789 return klass ? return_nested_in (klass, nested) : NULL;
7792 g_assert_not_reached ();
7796 token = MONO_TOKEN_TYPE_DEF | token;
7798 klass = mono_class_get_checked (image, token, error);
7800 return return_nested_in (klass, nested);
7805 * mono_class_from_name_checked:
7806 * @image: The MonoImage where the type is looked up in
7807 * @name_space: the type namespace
7808 * @name: the type short name.
7810 * Obtains a MonoClass with a given namespace and a given name which
7811 * is located in the given MonoImage.
7813 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
7814 * set if the class was not found or it will return NULL and set the error if there was a loading error.
7817 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7820 GHashTable *visited_images;
7822 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7824 klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
7826 g_hash_table_destroy (visited_images);
7832 * mono_class_from_name:
7833 * @image: The MonoImage where the type is looked up in
7834 * @name_space: the type namespace
7835 * @name: the type short name.
7837 * Obtains a MonoClass with a given namespace and a given name which
7838 * is located in the given MonoImage.
7840 * To reference nested classes, use the "/" character as a separator.
7841 * For example use "Foo/Bar" to reference the class Bar that is nested
7842 * inside Foo, like this: "class Foo { class Bar {} }".
7845 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7850 klass = mono_class_from_name_checked (image, name_space, name, &error);
7851 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
7857 * mono_class_load_from_name:
7858 * @image: The MonoImage where the type is looked up in
7859 * @name_space: the type namespace
7860 * @name: the type short name.
7862 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
7863 * This function should be used by the runtime for critical types to which there's no way to recover but crash
7864 * If they are missing. Thing of System.Object or System.String.
7867 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
7872 klass = mono_class_from_name_checked (image, name_space, name, &error);
7874 g_error ("Runtime critical type %s.%s not found", name_space, name);
7875 if (!mono_error_ok (&error))
7876 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
7881 * mono_class_try_load_from_name:
7882 * @image: The MonoImage where the type is looked up in
7883 * @name_space: the type namespace
7884 * @name: the type short name.
7886 * This function tries to load a type, returning the class was found or NULL otherwise.
7887 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
7889 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
7890 * a type that we would otherwise assume to be available but was not due some error.
7894 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
7899 klass = mono_class_from_name_checked (image, name_space, name, &error);
7900 if (!mono_error_ok (&error))
7901 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
7907 * mono_class_is_subclass_of:
7908 * @klass: class to probe if it is a subclass of another one
7909 * @klassc: the class we suspect is the base class
7910 * @check_interfaces: whether we should perform interface checks
7912 * This method determines whether @klass is a subclass of @klassc.
7914 * If the @check_interfaces flag is set, then if @klassc is an interface
7915 * this method return TRUE if the @klass implements the interface or
7916 * if @klass is an interface, if one of its base classes is @klass.
7918 * If @check_interfaces is false then, then if @klass is not an interface
7919 * then it returns TRUE if the @klass is a subclass of @klassc.
7921 * if @klass is an interface and @klassc is System.Object, then this function
7926 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
7927 gboolean check_interfaces)
7929 /* FIXME test for interfaces with variant generic arguments */
7930 mono_class_init (klass);
7931 mono_class_init (klassc);
7933 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
7934 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
7936 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
7939 for (i = 0; i < klass->interface_count; i ++) {
7940 MonoClass *ic = klass->interfaces [i];
7945 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
7950 * MS.NET thinks interfaces are a subclass of Object, so we think it as
7953 if (klassc == mono_defaults.object_class)
7960 mono_type_is_generic_argument (MonoType *type)
7962 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
7966 mono_class_has_variant_generic_params (MonoClass *klass)
7969 MonoGenericContainer *container;
7971 if (!mono_class_is_ginst (klass))
7974 container = mono_class_get_generic_container (mono_class_get_generic_class (klass)->container_class);
7976 for (i = 0; i < container->type_argc; ++i)
7977 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
7984 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
7986 if (target == candidate)
7989 if (check_for_reference_conv &&
7990 mono_type_is_generic_argument (&target->byval_arg) &&
7991 mono_type_is_generic_argument (&candidate->byval_arg)) {
7992 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
7993 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
7995 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
7998 if (!mono_class_is_assignable_from (target, candidate))
8004 * @container the generic container from the GTD
8005 * @klass: the class to be assigned to
8006 * @oklass: the source class
8008 * Both @klass and @oklass must be instances of the same generic interface.
8010 * Returns: TRUE if @klass can be assigned to a @klass variable
8013 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8016 MonoType **klass_argv, **oklass_argv;
8017 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8018 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8020 if (klass == oklass)
8023 /*Viable candidates are instances of the same generic interface*/
8024 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8027 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8028 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8030 for (j = 0; j < container->type_argc; ++j) {
8031 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8032 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8034 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8038 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8039 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8041 if (param1_class != param2_class) {
8042 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8043 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8045 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8046 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8056 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8058 MonoGenericParam *gparam, *ogparam;
8059 MonoGenericParamInfo *tinfo, *cinfo;
8060 MonoClass **candidate_class;
8061 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8064 if (target == candidate)
8066 if (target->byval_arg.type != candidate->byval_arg.type)
8069 gparam = target->byval_arg.data.generic_param;
8070 ogparam = candidate->byval_arg.data.generic_param;
8071 tinfo = mono_generic_param_info (gparam);
8072 cinfo = mono_generic_param_info (ogparam);
8074 class_constraint_satisfied = FALSE;
8075 valuetype_constraint_satisfied = FALSE;
8077 /*candidate must have a super set of target's special constraints*/
8078 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8079 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8081 if (cinfo->constraints) {
8082 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8083 MonoClass *cc = *candidate_class;
8085 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8086 class_constraint_satisfied = TRUE;
8087 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8088 valuetype_constraint_satisfied = TRUE;
8091 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8092 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8094 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8096 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8098 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8099 valuetype_constraint_satisfied)) {
8104 /*candidate type constraints must be a superset of target's*/
8105 if (tinfo->constraints) {
8106 MonoClass **target_class;
8107 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8108 MonoClass *tc = *target_class;
8111 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8112 * check it's constraints since it satisfy the constraint by itself.
8114 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8117 if (!cinfo->constraints)
8120 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8121 MonoClass *cc = *candidate_class;
8123 if (mono_class_is_assignable_from (tc, cc))
8127 * This happens when we have the following:
8129 * Bar<K> where K : IFace
8130 * Foo<T, U> where T : U where U : IFace
8132 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8135 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8136 if (mono_gparam_is_assignable_from (target, cc))
8140 if (!*candidate_class)
8145 /*candidate itself must have a constraint that satisfy target*/
8146 if (cinfo->constraints) {
8147 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8148 MonoClass *cc = *candidate_class;
8149 if (mono_class_is_assignable_from (target, cc))
8157 * mono_class_is_assignable_from:
8158 * @klass: the class to be assigned to
8159 * @oklass: the source class
8161 * Returns: TRUE if an instance of object oklass can be assigned to an
8162 * instance of object @klass
8165 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8168 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8170 mono_class_init (klass);
8172 if (!oklass->inited)
8173 mono_class_init (oklass);
8175 if (mono_class_has_failure (klass) || mono_class_has_failure (oklass))
8178 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8179 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8181 return mono_gparam_is_assignable_from (klass, oklass);
8184 if (MONO_CLASS_IS_INTERFACE (klass)) {
8185 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8186 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8187 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8191 for (i = 0; constraints [i]; ++i) {
8192 if (mono_class_is_assignable_from (klass, constraints [i]))
8200 /* interface_offsets might not be set for dynamic classes */
8201 if (mono_class_get_ref_info_handle (oklass) && !oklass->interface_bitmap) {
8203 * oklass might be a generic type parameter but they have
8204 * interface_offsets set.
8206 gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8207 if (!is_ok (&error)) {
8208 mono_error_cleanup (&error);
8213 if (!oklass->interface_bitmap)
8214 /* Happens with generic instances of not-yet created dynamic types */
8216 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8219 if (klass->is_array_special_interface && oklass->rank == 1) {
8220 //XXX we could offset this by having the cast target computed at JIT time
8221 //XXX we could go even further and emit a wrapper that would do the extra type check
8222 MonoClass *iface_klass = mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
8223 MonoClass *obj_klass = oklass->cast_class; //This gets us the cast class of element type of the array
8225 // If the target we're trying to cast to is a valuetype, we must account of weird valuetype equivalences such as IntEnum <> int or uint <> int
8226 // We can't apply it for ref types as this would go wrong with arrays - IList<byte[]> would have byte tested
8227 if (iface_klass->valuetype)
8228 iface_klass = iface_klass->cast_class;
8230 //array covariant casts only operates on scalar to scalar
8231 //This is so int[] can't be casted to IComparable<int>[]
8232 if (!(obj_klass->valuetype && !iface_klass->valuetype) && mono_class_is_assignable_from (iface_klass, obj_klass))
8236 if (mono_class_has_variant_generic_params (klass)) {
8238 mono_class_setup_interfaces (oklass, &error);
8239 if (!mono_error_ok (&error)) {
8240 mono_error_cleanup (&error);
8244 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8245 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8246 MonoClass *iface = oklass->interfaces_packed [i];
8248 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8253 } else if (klass->delegate) {
8254 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8256 }else if (klass->rank) {
8257 MonoClass *eclass, *eoclass;
8259 if (oklass->rank != klass->rank)
8262 /* vectors vs. one dimensional arrays */
8263 if (oklass->byval_arg.type != klass->byval_arg.type)
8266 eclass = klass->cast_class;
8267 eoclass = oklass->cast_class;
8270 * a is b does not imply a[] is b[] when a is a valuetype, and
8271 * b is a reference type.
8274 if (eoclass->valuetype) {
8275 if ((eclass == mono_defaults.enum_class) ||
8276 (eclass == mono_defaults.enum_class->parent) ||
8277 (eclass == mono_defaults.object_class))
8281 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8282 } else if (mono_class_is_nullable (klass)) {
8283 if (mono_class_is_nullable (oklass))
8284 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8286 return mono_class_is_assignable_from (klass->cast_class, oklass);
8287 } else if (klass == mono_defaults.object_class)
8290 return mono_class_has_parent (oklass, klass);
8293 /*Check if @oklass is variant compatible with @klass.*/
8295 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8298 MonoType **klass_argv, **oklass_argv;
8299 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8300 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8302 /*Viable candidates are instances of the same generic interface*/
8303 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8306 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8307 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8309 for (j = 0; j < container->type_argc; ++j) {
8310 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8311 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8313 if (param1_class->valuetype != param2_class->valuetype)
8317 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8318 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8320 if (param1_class != param2_class) {
8321 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8322 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8324 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8325 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8333 /*Check if @candidate implements the interface @target*/
8335 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8339 gboolean is_variant = mono_class_has_variant_generic_params (target);
8341 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8342 if (mono_class_is_variant_compatible_slow (target, candidate))
8347 if (candidate == target)
8350 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8351 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8352 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (candidate);
8354 if (tb && tb->interfaces) {
8355 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8356 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8357 MonoClass *iface_class;
8359 /* we can't realize the type here since it can do pretty much anything. */
8362 iface_class = mono_class_from_mono_type (iface->type);
8363 if (iface_class == target)
8365 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8367 if (mono_class_implement_interface_slow (target, iface_class))
8372 /*setup_interfaces don't mono_class_init anything*/
8373 /*FIXME this doesn't handle primitive type arrays.
8374 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8375 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8377 mono_class_setup_interfaces (candidate, &error);
8378 if (!mono_error_ok (&error)) {
8379 mono_error_cleanup (&error);
8383 for (i = 0; i < candidate->interface_count; ++i) {
8384 if (candidate->interfaces [i] == target)
8387 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8390 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8394 candidate = candidate->parent;
8395 } while (candidate);
8401 * Check if @oklass can be assigned to @klass.
8402 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8405 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8407 if (candidate == target)
8409 if (target == mono_defaults.object_class)
8412 if (mono_class_has_parent (candidate, target))
8415 /*If target is not an interface there is no need to check them.*/
8416 if (MONO_CLASS_IS_INTERFACE (target))
8417 return mono_class_implement_interface_slow (target, candidate);
8419 if (target->delegate && mono_class_has_variant_generic_params (target))
8420 return mono_class_is_variant_compatible (target, candidate, FALSE);
8423 MonoClass *eclass, *eoclass;
8425 if (target->rank != candidate->rank)
8428 /* vectors vs. one dimensional arrays */
8429 if (target->byval_arg.type != candidate->byval_arg.type)
8432 eclass = target->cast_class;
8433 eoclass = candidate->cast_class;
8436 * a is b does not imply a[] is b[] when a is a valuetype, and
8437 * b is a reference type.
8440 if (eoclass->valuetype) {
8441 if ((eclass == mono_defaults.enum_class) ||
8442 (eclass == mono_defaults.enum_class->parent) ||
8443 (eclass == mono_defaults.object_class))
8447 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8449 /*FIXME properly handle nullables */
8450 /*FIXME properly handle (M)VAR */
8455 * mono_class_get_cctor:
8456 * @klass: A MonoClass pointer
8458 * Returns: The static constructor of @klass if it exists, NULL otherwise.
8461 mono_class_get_cctor (MonoClass *klass)
8463 MonoCachedClassInfo cached_info;
8465 if (image_is_dynamic (klass->image)) {
8467 * has_cctor is not set for these classes because mono_class_init () is
8470 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8473 mono_class_init (klass);
8475 if (!klass->has_cctor)
8478 if (mono_class_is_ginst (klass) && !klass->methods)
8479 return mono_class_get_inflated_method (klass, mono_class_get_cctor (mono_class_get_generic_class (klass)->container_class));
8481 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8483 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8484 if (!mono_error_ok (&error))
8485 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8489 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8493 * mono_class_get_finalizer:
8494 * @klass: The MonoClass pointer
8496 * Returns: The finalizer method of @klass if it exists, NULL otherwise.
8499 mono_class_get_finalizer (MonoClass *klass)
8501 MonoCachedClassInfo cached_info;
8504 mono_class_init (klass);
8505 if (!mono_class_has_finalizer (klass))
8508 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8510 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8511 if (!mono_error_ok (&error))
8512 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8515 mono_class_setup_vtable (klass);
8516 return klass->vtable [finalize_slot];
8521 * mono_class_needs_cctor_run:
8522 * @klass: the MonoClass pointer
8523 * @caller: a MonoMethod describing the caller
8525 * Determines whenever the class has a static constructor and whenever it
8526 * needs to be called when executing CALLER.
8529 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8533 method = mono_class_get_cctor (klass);
8535 return (method == caller) ? FALSE : TRUE;
8541 * mono_class_array_element_size:
8544 * Returns: The number of bytes an element of type @klass
8545 * uses when stored into an array.
8548 mono_class_array_element_size (MonoClass *klass)
8550 MonoType *type = &klass->byval_arg;
8553 switch (type->type) {
8556 case MONO_TYPE_BOOLEAN:
8560 case MONO_TYPE_CHAR:
8569 case MONO_TYPE_CLASS:
8570 case MONO_TYPE_STRING:
8571 case MONO_TYPE_OBJECT:
8572 case MONO_TYPE_SZARRAY:
8573 case MONO_TYPE_ARRAY:
8574 return sizeof (gpointer);
8579 case MONO_TYPE_VALUETYPE:
8580 if (type->data.klass->enumtype) {
8581 type = mono_class_enum_basetype (type->data.klass);
8582 klass = klass->element_class;
8585 return mono_class_instance_size (klass) - sizeof (MonoObject);
8586 case MONO_TYPE_GENERICINST:
8587 type = &type->data.generic_class->container_class->byval_arg;
8590 case MONO_TYPE_MVAR: {
8593 return mono_type_size (type, &align);
8595 case MONO_TYPE_VOID:
8599 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8605 * mono_array_element_size:
8606 * @ac: pointer to a #MonoArrayClass
8608 * Returns: The size of single array element.
8611 mono_array_element_size (MonoClass *ac)
8613 g_assert (ac->rank);
8614 return ac->sizes.element_size;
8618 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8619 MonoGenericContext *context)
8622 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8623 g_assert (mono_error_ok (&error));
8628 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8629 MonoGenericContext *context, MonoError *error)
8631 mono_error_init (error);
8633 if (image_is_dynamic (image)) {
8634 MonoClass *tmp_handle_class;
8635 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
8637 mono_error_assert_ok (error);
8638 g_assert (tmp_handle_class);
8640 *handle_class = tmp_handle_class;
8642 if (tmp_handle_class == mono_defaults.typehandle_class)
8643 return &((MonoClass*)obj)->byval_arg;
8648 switch (token & 0xff000000) {
8649 case MONO_TOKEN_TYPE_DEF:
8650 case MONO_TOKEN_TYPE_REF:
8651 case MONO_TOKEN_TYPE_SPEC: {
8654 *handle_class = mono_defaults.typehandle_class;
8655 type = mono_type_get_checked (image, token, context, error);
8659 mono_class_init (mono_class_from_mono_type (type));
8660 /* We return a MonoType* as handle */
8663 case MONO_TOKEN_FIELD_DEF: {
8665 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8667 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8671 *handle_class = mono_defaults.fieldhandle_class;
8672 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8676 mono_class_init (klass);
8677 return mono_class_get_field (klass, token);
8679 case MONO_TOKEN_METHOD_DEF:
8680 case MONO_TOKEN_METHOD_SPEC: {
8682 meth = mono_get_method_checked (image, token, NULL, context, error);
8684 *handle_class = mono_defaults.methodhandle_class;
8690 case MONO_TOKEN_MEMBER_REF: {
8691 guint32 cols [MONO_MEMBERREF_SIZE];
8693 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8694 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8695 mono_metadata_decode_blob_size (sig, &sig);
8696 if (*sig == 0x6) { /* it's a field */
8698 MonoClassField *field;
8699 field = mono_field_from_token_checked (image, token, &klass, context, error);
8701 *handle_class = mono_defaults.fieldhandle_class;
8705 meth = mono_get_method_checked (image, token, NULL, context, error);
8707 *handle_class = mono_defaults.methodhandle_class;
8712 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8718 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
8720 MonoClass *handle_class;
8721 mono_error_init (error);
8722 return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
8726 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
8728 return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
8731 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8734 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8736 get_cached_class_info = func;
8740 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8742 if (!get_cached_class_info)
8745 return get_cached_class_info (klass, res);
8749 mono_install_get_class_from_name (MonoGetClassFromName func)
8751 get_class_from_name = func;
8755 * mono_class_get_image:
8757 * Use this method to get the `MonoImage*` where this class came from.
8759 * Returns: The image where this class is defined.
8762 mono_class_get_image (MonoClass *klass)
8764 return klass->image;
8768 * mono_class_get_element_class:
8769 * @klass: the MonoClass to act on
8771 * Use this function to get the element class of an array.
8773 * Returns: The element class of an array.
8776 mono_class_get_element_class (MonoClass *klass)
8778 return klass->element_class;
8782 * mono_class_is_valuetype:
8783 * @klass: the MonoClass to act on
8785 * Use this method to determine if the provided `MonoClass*` represents a value type,
8786 * or a reference type.
8788 * Returns: TRUE if the MonoClass represents a ValueType, FALSE if it represents a reference type.
8791 mono_class_is_valuetype (MonoClass *klass)
8793 return klass->valuetype;
8797 * mono_class_is_enum:
8798 * @klass: the MonoClass to act on
8800 * Use this function to determine if the provided `MonoClass*` represents an enumeration.
8802 * Returns: TRUE if the MonoClass represents an enumeration.
8805 mono_class_is_enum (MonoClass *klass)
8807 return klass->enumtype;
8811 * mono_class_enum_basetype:
8812 * @klass: the MonoClass to act on
8814 * Use this function to get the underlying type for an enumeration value.
8816 * Returns: The underlying type representation for an enumeration.
8819 mono_class_enum_basetype (MonoClass *klass)
8821 if (klass->element_class == klass)
8822 /* SRE or broken types */
8825 return &klass->element_class->byval_arg;
8829 * mono_class_get_parent
8830 * @klass: the MonoClass to act on
8832 * Returns: The parent class for this class.
8835 mono_class_get_parent (MonoClass *klass)
8837 return klass->parent;
8841 * mono_class_get_nesting_type:
8842 * @klass: the MonoClass to act on
8844 * Use this function to obtain the class that the provided `MonoClass*` is nested on.
8846 * If the return is NULL, this indicates that this class is not nested.
8848 * Returns: The container type where this type is nested or NULL if this type is not a nested type.
8851 mono_class_get_nesting_type (MonoClass *klass)
8853 return klass->nested_in;
8857 * mono_class_get_rank:
8858 * @klass: the MonoClass to act on
8860 * Returns: The rank for the array (the number of dimensions).
8863 mono_class_get_rank (MonoClass *klass)
8869 * mono_class_get_name
8870 * @klass: the MonoClass to act on
8872 * Returns: The name of the class.
8875 mono_class_get_name (MonoClass *klass)
8881 * mono_class_get_namespace:
8882 * @klass: the MonoClass to act on
8884 * Returns: The namespace of the class.
8887 mono_class_get_namespace (MonoClass *klass)
8889 return klass->name_space;
8893 * mono_class_get_type:
8894 * @klass: the MonoClass to act on
8896 * This method returns the internal Type representation for the class.
8898 * Returns: The MonoType from the class.
8901 mono_class_get_type (MonoClass *klass)
8903 return &klass->byval_arg;
8907 * mono_class_get_type_token:
8908 * @klass: the MonoClass to act on
8910 * This method returns type token for the class.
8912 * Returns: The type token for the class.
8915 mono_class_get_type_token (MonoClass *klass)
8917 return klass->type_token;
8921 * mono_class_get_byref_type:
8922 * @klass: the MonoClass to act on
8927 mono_class_get_byref_type (MonoClass *klass)
8929 return &klass->this_arg;
8933 * mono_class_num_fields:
8934 * @klass: the MonoClass to act on
8936 * Returns: The number of static and instance fields in the class.
8939 mono_class_num_fields (MonoClass *klass)
8941 return mono_class_get_field_count (klass);
8945 * mono_class_num_methods:
8946 * @klass: the MonoClass to act on
8948 * Returns: The number of methods in the class.
8951 mono_class_num_methods (MonoClass *klass)
8953 return mono_class_get_method_count (klass);
8957 * mono_class_num_properties
8958 * @klass: the MonoClass to act on
8960 * Returns: The number of properties in the class.
8963 mono_class_num_properties (MonoClass *klass)
8965 mono_class_setup_properties (klass);
8967 return mono_class_get_property_info (klass)->count;
8971 * mono_class_num_events:
8972 * @klass: the MonoClass to act on
8974 * Returns: The number of events in the class.
8977 mono_class_num_events (MonoClass *klass)
8979 mono_class_setup_events (klass);
8981 return mono_class_get_event_info (klass)->count;
8985 * mono_class_get_fields:
8986 * @klass: the MonoClass to act on
8988 * This routine is an iterator routine for retrieving the fields in a class.
8990 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8991 * iterate over all of the elements. When no more values are
8992 * available, the return value is NULL.
8994 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
8997 mono_class_get_fields (MonoClass* klass, gpointer *iter)
8999 MonoClassField* field;
9003 mono_class_setup_fields (klass);
9004 if (mono_class_has_failure (klass))
9006 /* start from the first */
9007 if (mono_class_get_field_count (klass)) {
9008 *iter = &klass->fields [0];
9009 return &klass->fields [0];
9015 field = (MonoClassField *)*iter;
9017 if (field < &klass->fields [mono_class_get_field_count (klass)]) {
9025 * mono_class_get_methods
9026 * @klass: the MonoClass to act on
9028 * This routine is an iterator routine for retrieving the fields in a class.
9030 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9031 * iterate over all of the elements. When no more values are
9032 * available, the return value is NULL.
9034 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
9037 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9039 MonoMethod** method;
9043 mono_class_setup_methods (klass);
9046 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9047 * FIXME we should better report this error to the caller
9049 if (!klass->methods)
9051 /* start from the first */
9052 if (mono_class_get_method_count (klass)) {
9053 *iter = &klass->methods [0];
9054 return klass->methods [0];
9060 method = (MonoMethod **)*iter;
9062 if (method < &klass->methods [mono_class_get_method_count (klass)]) {
9070 * mono_class_get_virtual_methods:
9072 * Iterate over the virtual methods of KLASS.
9074 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9077 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9079 MonoMethod** method;
9082 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9084 mono_class_setup_methods (klass);
9086 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9087 * FIXME we should better report this error to the caller
9089 if (!klass->methods)
9091 /* start from the first */
9092 method = &klass->methods [0];
9094 method = (MonoMethod **)*iter;
9097 int mcount = mono_class_get_method_count (klass);
9098 while (method < &klass->methods [mcount]) {
9099 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9103 if (method < &klass->methods [mcount]) {
9110 /* Search directly in metadata to avoid calling setup_methods () */
9111 MonoMethod *res = NULL;
9117 start_index = GPOINTER_TO_UINT (*iter);
9120 int first_idx = mono_class_get_first_method_idx (klass);
9121 int mcount = mono_class_get_method_count (klass);
9122 for (i = start_index; i < mcount; ++i) {
9125 /* first_idx points into the methodptr table */
9126 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
9128 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9134 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9135 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9137 /* Add 1 here so the if (*iter) check fails */
9138 *iter = GUINT_TO_POINTER (i + 1);
9147 * mono_class_get_properties:
9148 * @klass: the MonoClass to act on
9150 * This routine is an iterator routine for retrieving the properties in a class.
9152 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9153 * iterate over all of the elements. When no more values are
9154 * available, the return value is NULL.
9156 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9159 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9161 MonoProperty* property;
9165 mono_class_setup_properties (klass);
9166 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
9167 /* start from the first */
9169 *iter = &info->properties [0];
9170 return (MonoProperty *)*iter;
9176 property = (MonoProperty *)*iter;
9178 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
9179 if (property < &info->properties [info->count]) {
9181 return (MonoProperty *)*iter;
9187 * mono_class_get_events:
9188 * @klass: the MonoClass to act on
9190 * This routine is an iterator routine for retrieving the properties in a class.
9192 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9193 * iterate over all of the elements. When no more values are
9194 * available, the return value is NULL.
9196 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9199 mono_class_get_events (MonoClass* klass, gpointer *iter)
9205 mono_class_setup_events (klass);
9206 MonoClassEventInfo *info = mono_class_get_event_info (klass);
9207 /* start from the first */
9209 *iter = &info->events [0];
9210 return (MonoEvent *)*iter;
9216 event = (MonoEvent *)*iter;
9218 MonoClassEventInfo *info = mono_class_get_event_info (klass);
9219 if (event < &info->events [info->count]) {
9221 return (MonoEvent *)*iter;
9227 * mono_class_get_interfaces
9228 * @klass: the MonoClass to act on
9230 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9232 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9233 * iterate over all of the elements. When no more values are
9234 * available, the return value is NULL.
9236 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9239 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9247 mono_class_init (klass);
9248 if (!klass->interfaces_inited) {
9249 mono_class_setup_interfaces (klass, &error);
9250 if (!mono_error_ok (&error)) {
9251 mono_error_cleanup (&error);
9255 /* start from the first */
9256 if (klass->interface_count) {
9257 *iter = &klass->interfaces [0];
9258 return klass->interfaces [0];
9264 iface = (MonoClass **)*iter;
9266 if (iface < &klass->interfaces [klass->interface_count]) {
9274 setup_nested_types (MonoClass *klass)
9277 GList *classes, *nested_classes, *l;
9280 if (klass->nested_classes_inited)
9283 if (!klass->type_token)
9284 klass->nested_classes_inited = TRUE;
9286 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9290 guint32 cols [MONO_NESTED_CLASS_SIZE];
9291 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9292 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9293 if (!mono_error_ok (&error)) {
9294 /*FIXME don't swallow the error message*/
9295 mono_error_cleanup (&error);
9297 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9301 classes = g_list_prepend (classes, nclass);
9303 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9306 nested_classes = NULL;
9307 for (l = classes; l; l = l->next)
9308 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9309 g_list_free (classes);
9311 mono_loader_lock ();
9312 if (!klass->nested_classes_inited) {
9313 mono_class_set_nested_classes_property (klass, nested_classes);
9314 mono_memory_barrier ();
9315 klass->nested_classes_inited = TRUE;
9317 mono_loader_unlock ();
9321 * mono_class_get_nested_types
9322 * @klass: the MonoClass to act on
9324 * This routine is an iterator routine for retrieving the nested types of a class.
9325 * This works only if @klass is non-generic, or a generic type definition.
9327 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9328 * iterate over all of the elements. When no more values are
9329 * available, the return value is NULL.
9331 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9334 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9340 if (!klass->nested_classes_inited)
9341 setup_nested_types (klass);
9344 GList *nested_classes = mono_class_get_nested_classes_property (klass);
9345 /* start from the first */
9346 if (nested_classes) {
9347 *iter = nested_classes;
9348 return (MonoClass *)nested_classes->data;
9350 /* no nested types */
9354 item = (GList *)*iter;
9358 return (MonoClass *)item->data;
9365 * mono_class_is_delegate
9366 * @klass: the MonoClass to act on
9368 * Returns: TRUE if the MonoClass represents a System.Delegate.
9371 mono_class_is_delegate (MonoClass *klass)
9373 return klass->delegate;
9377 * mono_class_implements_interface
9378 * @klass: The MonoClass to act on
9379 * @interface: The interface to check if @klass implements.
9381 * Returns: TRUE if @klass implements @interface.
9384 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9386 return mono_class_is_assignable_from (iface, klass);
9390 * mono_field_get_name:
9391 * @field: the MonoClassField to act on
9393 * Returns: The name of the field.
9396 mono_field_get_name (MonoClassField *field)
9402 * mono_field_get_type:
9403 * @field: the MonoClassField to act on
9405 * Returns: MonoType of the field.
9408 mono_field_get_type (MonoClassField *field)
9411 MonoType *type = mono_field_get_type_checked (field, &error);
9412 if (!mono_error_ok (&error)) {
9413 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9414 mono_error_cleanup (&error);
9421 * mono_field_get_type_checked:
9422 * @field: the MonoClassField to act on
9423 * @error: used to return any erro found while retrieving @field type
9425 * Returns: MonoType of the field.
9428 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9430 mono_error_init (error);
9432 mono_field_resolve_type (field, error);
9437 * mono_field_get_parent:
9438 * @field: the MonoClassField to act on
9440 * Returns: MonoClass where the field was defined.
9443 mono_field_get_parent (MonoClassField *field)
9445 return field->parent;
9449 * mono_field_get_flags;
9450 * @field: the MonoClassField to act on
9452 * The metadata flags for a field are encoded using the
9453 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9455 * Returns: The flags for the field.
9458 mono_field_get_flags (MonoClassField *field)
9461 return mono_field_resolve_flags (field);
9462 return field->type->attrs;
9466 * mono_field_get_offset:
9467 * @field: the MonoClassField to act on
9469 * Returns: The field offset.
9472 mono_field_get_offset (MonoClassField *field)
9474 return field->offset;
9478 mono_field_get_rva (MonoClassField *field)
9482 MonoClass *klass = field->parent;
9483 MonoFieldDefaultValue *def_values;
9485 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9487 def_values = mono_class_get_field_def_values (klass);
9489 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
9491 mono_class_set_field_def_values (klass, def_values);
9494 field_index = mono_field_get_index (field);
9496 if (!def_values [field_index].data && !image_is_dynamic (klass->image)) {
9497 int first_field_idx = mono_class_get_first_field_idx (klass);
9498 mono_metadata_field_info (field->parent->image, first_field_idx + field_index, NULL, &rva, NULL);
9500 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9501 def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9504 return def_values [field_index].data;
9508 * mono_field_get_data:
9509 * @field: the MonoClassField to act on
9511 * Returns: A pointer to the metadata constant value or to the field
9512 * data if it has an RVA flag.
9515 mono_field_get_data (MonoClassField *field)
9517 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9518 MonoTypeEnum def_type;
9520 return mono_class_get_field_default_value (field, &def_type);
9521 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9522 return mono_field_get_rva (field);
9529 * mono_property_get_name:
9530 * @prop: the MonoProperty to act on
9532 * Returns: The name of the property
9535 mono_property_get_name (MonoProperty *prop)
9541 * mono_property_get_set_method
9542 * @prop: the MonoProperty to act on.
9544 * Returns: The setter method of the property (A MonoMethod)
9547 mono_property_get_set_method (MonoProperty *prop)
9553 * mono_property_get_get_method
9554 * @prop: the MonoProperty to act on.
9556 * Returns: The setter method of the property (A MonoMethod)
9559 mono_property_get_get_method (MonoProperty *prop)
9565 * mono_property_get_parent:
9566 * @prop: the MonoProperty to act on.
9568 * Returns: The MonoClass where the property was defined.
9571 mono_property_get_parent (MonoProperty *prop)
9573 return prop->parent;
9577 * mono_property_get_flags:
9578 * @prop: the MonoProperty to act on.
9580 * The metadata flags for a property are encoded using the
9581 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9583 * Returns: The flags for the property.
9586 mono_property_get_flags (MonoProperty *prop)
9592 * mono_event_get_name:
9593 * @event: the MonoEvent to act on
9595 * Returns: The name of the event.
9598 mono_event_get_name (MonoEvent *event)
9604 * mono_event_get_add_method:
9605 * @event: The MonoEvent to act on.
9607 * Returns: The @add' method for the event (a MonoMethod).
9610 mono_event_get_add_method (MonoEvent *event)
9616 * mono_event_get_remove_method:
9617 * @event: The MonoEvent to act on.
9619 * Returns: The @remove method for the event (a MonoMethod).
9622 mono_event_get_remove_method (MonoEvent *event)
9624 return event->remove;
9628 * mono_event_get_raise_method:
9629 * @event: The MonoEvent to act on.
9631 * Returns: The @raise method for the event (a MonoMethod).
9634 mono_event_get_raise_method (MonoEvent *event)
9636 return event->raise;
9640 * mono_event_get_parent:
9641 * @event: the MonoEvent to act on.
9643 * Returns: The MonoClass where the event is defined.
9646 mono_event_get_parent (MonoEvent *event)
9648 return event->parent;
9652 * mono_event_get_flags
9653 * @event: the MonoEvent to act on.
9655 * The metadata flags for an event are encoded using the
9656 * EVENT_* constants. See the tabledefs.h file for details.
9658 * Returns: The flags for the event.
9661 mono_event_get_flags (MonoEvent *event)
9663 return event->attrs;
9667 * mono_class_get_method_from_name:
9668 * @klass: where to look for the method
9669 * @name: name of the method
9670 * @param_count: number of parameters. -1 for any number.
9672 * Obtains a MonoMethod with a given name and number of parameters.
9673 * It only works if there are no multiple signatures for any given method name.
9676 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9678 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9682 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9684 MonoMethod *res = NULL;
9687 /* Search directly in the metadata to avoid calling setup_methods () */
9688 int first_idx = mono_class_get_first_method_idx (klass);
9689 int mcount = mono_class_get_method_count (klass);
9690 for (i = 0; i < mcount; ++i) {
9692 guint32 cols [MONO_METHOD_SIZE];
9694 MonoMethodSignature *sig;
9696 /* first_idx points into the methodptr table */
9697 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, first_idx + i, cols, MONO_METHOD_SIZE);
9699 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9700 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9702 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9705 if (param_count == -1) {
9709 sig = mono_method_signature_checked (method, &error);
9711 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9714 if (sig->param_count == param_count) {
9725 * mono_class_get_method_from_name_flags:
9726 * @klass: where to look for the method
9727 * @name_space: name of the method
9728 * @param_count: number of parameters. -1 for any number.
9729 * @flags: flags which must be set in the method
9731 * Obtains a MonoMethod with a given name and number of parameters.
9732 * It only works if there are no multiple signatures for any given method name.
9735 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9737 MonoMethod *res = NULL;
9740 mono_class_init (klass);
9742 if (mono_class_is_ginst (klass) && !klass->methods) {
9743 res = mono_class_get_method_from_name_flags (mono_class_get_generic_class (klass)->container_class, name, param_count, flags);
9746 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9747 if (!mono_error_ok (&error))
9748 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9753 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9754 mono_class_setup_methods (klass);
9756 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9757 See mono/tests/array_load_exception.il
9758 FIXME we should better report this error to the caller
9760 if (!klass->methods)
9762 int mcount = mono_class_get_method_count (klass);
9763 for (i = 0; i < mcount; ++i) {
9764 MonoMethod *method = klass->methods [i];
9766 if (method->name[0] == name [0] &&
9767 !strcmp (name, method->name) &&
9768 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9769 ((method->flags & flags) == flags)) {
9776 res = find_method_in_metadata (klass, name, param_count, flags);
9783 * mono_class_set_failure:
9784 * @klass: class in which the failure was detected
9785 * @ex_type: the kind of exception/error to be thrown (later)
9786 * @ex_data: exception data (specific to each type of exception/error)
9788 * Keep a detected failure informations in the class for later processing.
9789 * Note that only the first failure is kept.
9791 * LOCKING: Acquires the loader lock.
9794 mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error)
9796 g_assert (boxed_error != NULL);
9798 if (mono_class_has_failure (klass))
9801 mono_loader_lock ();
9802 klass->has_failure = 1;
9803 mono_class_set_exception_data (klass, boxed_error);
9804 mono_loader_unlock ();
9810 mono_class_has_failure (const MonoClass *klass)
9812 g_assert (klass != NULL);
9813 return klass->has_failure != 0;
9818 * mono_class_set_type_load_failure:
9819 * @klass: class in which the failure was detected
9820 * @fmt: Printf-style error message string.
9822 * Collect detected failure informaion in the class for later processing.
9823 * The error is stored as a MonoErrorBoxed as with mono_error_set_type_load_class ()
9824 * Note that only the first failure is kept.
9826 * Returns FALSE if a failure was already set on the class, or TRUE otherwise.
9828 * LOCKING: Acquires the loader lock.
9831 mono_class_set_type_load_failure (MonoClass *klass, const char * fmt, ...)
9833 MonoError prepare_error;
9836 if (mono_class_has_failure (klass))
9839 mono_error_init (&prepare_error);
9841 va_start (args, fmt);
9842 mono_error_vset_type_load_class (&prepare_error, klass, fmt, args);
9845 MonoErrorBoxed *box = mono_error_box (&prepare_error, klass->image);
9846 mono_error_cleanup (&prepare_error);
9847 return mono_class_set_failure (klass, box);
9851 * mono_classes_init:
9853 * Initialize the resources used by this module.
9856 mono_classes_init (void)
9858 mono_os_mutex_init (&classes_mutex);
9860 mono_native_tls_alloc (&setup_fields_tls_id, NULL);
9861 mono_native_tls_alloc (&init_pending_tls_id, NULL);
9863 mono_counters_register ("MonoClassDef count",
9864 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_def_count);
9865 mono_counters_register ("MonoClassGtd count",
9866 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gtd_count);
9867 mono_counters_register ("MonoClassGenericInst count",
9868 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ginst_count);
9869 mono_counters_register ("MonoClassGenericParam count",
9870 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gparam_count);
9871 mono_counters_register ("MonoClassArray count",
9872 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_array_count);
9873 mono_counters_register ("MonoClassPointer count",
9874 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_pointer_count);
9875 mono_counters_register ("Inflated methods size",
9876 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9877 mono_counters_register ("Inflated classes size",
9878 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9879 mono_counters_register ("MonoClass size",
9880 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9884 * mono_classes_cleanup:
9886 * Free the resources used by this module.
9889 mono_classes_cleanup (void)
9891 mono_native_tls_free (setup_fields_tls_id);
9892 mono_native_tls_free (init_pending_tls_id);
9894 if (global_interface_bitset)
9895 mono_bitset_free (global_interface_bitset);
9896 global_interface_bitset = NULL;
9897 mono_os_mutex_destroy (&classes_mutex);
9901 * mono_class_get_exception_for_failure:
9902 * @klass: class in which the failure was detected
9904 * Return a constructed MonoException than the caller can then throw
9905 * using mono_raise_exception - or NULL if no failure is present (or
9906 * doesn't result in an exception).
9909 mono_class_get_exception_for_failure (MonoClass *klass)
9911 if (!mono_class_has_failure (klass))
9913 MonoError unboxed_error;
9914 mono_error_init (&unboxed_error);
9915 mono_error_set_for_class_failure (&unboxed_error, klass);
9916 return mono_error_convert_to_exception (&unboxed_error);
9920 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
9922 outer_klass = mono_class_get_generic_type_definition (outer_klass);
9923 inner_klass = mono_class_get_generic_type_definition (inner_klass);
9925 if (outer_klass == inner_klass)
9927 inner_klass = inner_klass->nested_in;
9928 } while (inner_klass);
9933 mono_class_get_generic_type_definition (MonoClass *klass)
9935 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
9936 return gklass ? gklass->container_class : klass;
9940 * Check if @klass is a subtype of @parent ignoring generic instantiations.
9942 * Generic instantiations are ignored for all super types of @klass.
9944 * Visibility checks ignoring generic instantiations.
9947 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
9950 klass = mono_class_get_generic_type_definition (klass);
9951 parent = mono_class_get_generic_type_definition (parent);
9952 mono_class_setup_supertypes (klass);
9954 for (i = 0; i < klass->idepth; ++i) {
9955 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
9961 * Subtype can only access parent members with family protection if the site object
9962 * is subclass of Subtype. For example:
9963 * class A { protected int x; }
9965 * void valid_access () {
9969 * void invalid_access () {
9976 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
9978 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
9981 if (context_klass == NULL)
9983 /*if access_klass is not member_klass context_klass must be type compat*/
9984 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
9990 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
9993 if (accessing == accessed)
9995 if (!accessed || !accessing)
9998 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
9999 * anywhere so untrusted friends are not safe to access platform's code internals */
10000 if (mono_security_core_clr_enabled ()) {
10001 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10005 mono_assembly_load_friends (accessed);
10006 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10007 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10008 /* Be conservative with checks */
10009 if (!friend_->name)
10011 if (strcmp (accessing->aname.name, friend_->name))
10013 if (friend_->public_key_token [0]) {
10014 if (!accessing->aname.public_key_token [0])
10016 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10025 * If klass is a generic type or if it is derived from a generic type, return the
10026 * MonoClass of the generic definition
10027 * Returns NULL if not found
10030 get_generic_definition_class (MonoClass *klass)
10033 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
10034 if (gklass && gklass->container_class)
10035 return gklass->container_class;
10036 klass = klass->parent;
10042 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10045 for (i = 0; i < ginst->type_argc; ++i) {
10046 MonoType *type = ginst->type_argv[i];
10047 switch (type->type) {
10048 case MONO_TYPE_SZARRAY:
10049 if (!can_access_type (access_klass, type->data.klass))
10052 case MONO_TYPE_ARRAY:
10053 if (!can_access_type (access_klass, type->data.array->eklass))
10056 case MONO_TYPE_PTR:
10057 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10060 case MONO_TYPE_CLASS:
10061 case MONO_TYPE_VALUETYPE:
10062 case MONO_TYPE_GENERICINST:
10063 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10073 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10077 if (access_klass == member_klass)
10080 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10083 if (access_klass->element_class && !access_klass->enumtype)
10084 access_klass = access_klass->element_class;
10086 if (member_klass->element_class && !member_klass->enumtype)
10087 member_klass = member_klass->element_class;
10089 access_level = mono_class_get_flags (member_klass) & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10091 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10094 if (mono_class_is_ginst (member_klass) && !can_access_instantiation (access_klass, mono_class_get_generic_class (member_klass)->context.class_inst))
10097 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10100 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10103 /*Non nested type with nested visibility. We just fail it.*/
10104 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10107 switch (access_level) {
10108 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10109 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10111 case TYPE_ATTRIBUTE_PUBLIC:
10114 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10117 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10118 return is_nesting_type (member_klass, access_klass);
10120 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10121 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10123 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10124 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10126 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10127 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10128 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10130 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10131 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10132 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10137 /* FIXME: check visibility of type, too */
10139 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10141 MonoClass *member_generic_def;
10142 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10145 MonoGenericClass *access_gklass = mono_class_try_get_generic_class (access_klass);
10146 if (((access_gklass && access_gklass->container_class) ||
10147 mono_class_is_gtd (access_klass)) &&
10148 (member_generic_def = get_generic_definition_class (member_klass))) {
10149 MonoClass *access_container;
10151 if (mono_class_is_gtd (access_klass))
10152 access_container = access_klass;
10154 access_container = access_gklass->container_class;
10156 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10160 /* Partition I 8.5.3.2 */
10161 /* the access level values are the same for fields and methods */
10162 switch (access_level) {
10163 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10164 /* same compilation unit */
10165 return access_klass->image == member_klass->image;
10166 case FIELD_ATTRIBUTE_PRIVATE:
10167 return access_klass == member_klass;
10168 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10169 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10170 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10173 case FIELD_ATTRIBUTE_ASSEMBLY:
10174 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10175 case FIELD_ATTRIBUTE_FAMILY:
10176 if (is_valid_family_access (access_klass, member_klass, context_klass))
10179 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10180 if (is_valid_family_access (access_klass, member_klass, context_klass))
10182 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10183 case FIELD_ATTRIBUTE_PUBLIC:
10190 * mono_method_can_access_field:
10191 * @method: Method that will attempt to access the field
10192 * @field: the field to access
10194 * Used to determine if a method is allowed to access the specified field.
10196 * Returns: TRUE if the given @method is allowed to access the @field while following
10197 * the accessibility rules of the CLI.
10200 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10202 /* FIXME: check all overlapping fields */
10203 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10205 MonoClass *nested = method->klass->nested_in;
10207 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10210 nested = nested->nested_in;
10217 * mono_method_can_access_method:
10218 * @method: Method that will attempt to access the other method
10219 * @called: the method that we want to probe for accessibility.
10221 * Used to determine if the @method is allowed to access the specified @called method.
10223 * Returns: TRUE if the given @method is allowed to invoke the @called while following
10224 * the accessibility rules of the CLI.
10227 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10229 method = mono_method_get_method_definition (method);
10230 called = mono_method_get_method_definition (called);
10231 return mono_method_can_access_method_full (method, called, NULL);
10235 * mono_method_can_access_method_full:
10236 * @method: The caller method
10237 * @called: The called method
10238 * @context_klass: The static type on stack of the owner @called object used
10240 * This function must be used with instance calls, as they have more strict family accessibility.
10241 * It can be used with static methods, but context_klass should be NULL.
10243 * Returns: TRUE if caller have proper visibility and acessibility to @called
10246 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10248 /* Wrappers are except from access checks */
10249 if (method->wrapper_type != MONO_WRAPPER_NONE || called->wrapper_type != MONO_WRAPPER_NONE)
10252 MonoClass *access_class = method->klass;
10253 MonoClass *member_class = called->klass;
10254 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10256 MonoClass *nested = access_class->nested_in;
10258 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10261 nested = nested->nested_in;
10268 can = can_access_type (access_class, member_class);
10270 MonoClass *nested = access_class->nested_in;
10272 can = can_access_type (nested, member_class);
10275 nested = nested->nested_in;
10282 if (called->is_inflated) {
10283 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10284 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10293 * mono_method_can_access_field_full:
10294 * @method: The caller method
10295 * @field: The accessed field
10296 * @context_klass: The static type on stack of the owner @field object used
10298 * This function must be used with instance fields, as they have more strict family accessibility.
10299 * It can be used with static fields, but context_klass should be NULL.
10301 * Returns: TRUE if caller have proper visibility and acessibility to @field
10304 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10306 MonoClass *access_class = method->klass;
10307 MonoClass *member_class = field->parent;
10308 /* FIXME: check all overlapping fields */
10309 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10311 MonoClass *nested = access_class->nested_in;
10313 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10316 nested = nested->nested_in;
10323 can = can_access_type (access_class, member_class);
10325 MonoClass *nested = access_class->nested_in;
10327 can = can_access_type (nested, member_class);
10330 nested = nested->nested_in;
10340 * mono_class_can_access_class:
10341 * @source_class: The source class
10342 * @target_class: The accessed class
10344 * This function returns is @target_class is visible to @source_class
10346 * Returns: TRUE if source have proper visibility and acessibility to target
10349 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10351 return can_access_type (source_class, target_class);
10355 * mono_type_is_valid_enum_basetype:
10356 * @type: The MonoType to check
10358 * Returns: TRUE if the type can be used as the basetype of an enum
10360 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10361 switch (type->type) {
10364 case MONO_TYPE_BOOLEAN:
10367 case MONO_TYPE_CHAR:
10381 * mono_class_is_valid_enum:
10382 * @klass: An enum class to be validated
10384 * This method verify the required properties an enum should have.
10386 * Returns: TRUE if the informed enum class is valid
10388 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10389 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10390 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10393 mono_class_is_valid_enum (MonoClass *klass)
10395 MonoClassField * field;
10396 gpointer iter = NULL;
10397 gboolean found_base_field = FALSE;
10399 g_assert (klass->enumtype);
10400 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10401 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10405 if (!mono_class_is_auto_layout (klass))
10408 while ((field = mono_class_get_fields (klass, &iter))) {
10409 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10410 if (found_base_field)
10412 found_base_field = TRUE;
10413 if (!mono_type_is_valid_enum_basetype (field->type))
10418 if (!found_base_field)
10421 if (mono_class_get_method_count (klass) > 0)
10428 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10430 return gklass->context.class_inst == mono_class_get_generic_container (gklass->container_class)->context.class_inst;
10434 * mono_class_setup_interface_id:
10436 * Initializes MonoClass::interface_id if required.
10438 * LOCKING: Acquires the loader lock.
10441 mono_class_setup_interface_id (MonoClass *klass)
10443 mono_loader_lock ();
10444 if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10445 klass->interface_id = mono_get_unique_iid (klass);
10446 mono_loader_unlock ();
10450 * mono_class_setup_interfaces:
10452 * Initialize klass->interfaces/interfaces_count.
10453 * LOCKING: Acquires the loader lock.
10454 * This function can fail the type.
10457 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10459 int i, interface_count;
10460 MonoClass **interfaces;
10462 mono_error_init (error);
10464 if (klass->interfaces_inited)
10467 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10468 MonoType *args [1];
10470 /* generic IList, ICollection, IEnumerable */
10471 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10472 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10474 args [0] = &klass->element_class->byval_arg;
10475 interfaces [0] = mono_class_bind_generic_parameters (
10476 mono_defaults.generic_ilist_class, 1, args, FALSE);
10477 if (interface_count > 1)
10478 interfaces [1] = mono_class_bind_generic_parameters (
10479 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10480 } else if (mono_class_is_ginst (klass)) {
10481 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
10483 mono_class_setup_interfaces (gklass, error);
10484 if (!mono_error_ok (error)) {
10485 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10489 interface_count = gklass->interface_count;
10490 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10491 for (i = 0; i < interface_count; i++) {
10492 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (mono_class_get_generic_class (klass)), error);
10493 if (!mono_error_ok (error)) {
10494 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10499 interface_count = 0;
10503 mono_image_lock (klass->image);
10505 if (!klass->interfaces_inited) {
10506 klass->interface_count = interface_count;
10507 klass->interfaces = interfaces;
10509 mono_memory_barrier ();
10511 klass->interfaces_inited = TRUE;
10514 mono_image_unlock (klass->image);
10518 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10520 MonoClass *klass = field->parent;
10521 MonoImage *image = klass->image;
10522 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10524 int field_idx = field - klass->fields;
10526 mono_error_init (error);
10529 MonoClassField *gfield = >d->fields [field_idx];
10530 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10531 if (!mono_error_ok (error)) {
10532 char *full_name = mono_type_get_full_name (gtd);
10533 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));
10534 g_free (full_name);
10537 ftype = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10538 if (!mono_error_ok (error)) {
10539 char *full_name = mono_type_get_full_name (klass);
10540 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));
10541 g_free (full_name);
10545 guint32 cols [MONO_FIELD_SIZE];
10546 MonoGenericContainer *container = NULL;
10547 int idx = mono_class_get_first_field_idx (klass) + field_idx;
10549 /*FIXME, in theory we do not lazy load SRE fields*/
10550 g_assert (!image_is_dynamic (image));
10552 if (mono_class_is_gtd (klass)) {
10553 container = mono_class_get_generic_container (klass);
10555 container = mono_class_get_generic_container (gtd);
10556 g_assert (container);
10559 /* first_field_idx and idx points into the fieldptr table */
10560 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10562 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10563 char *full_name = mono_type_get_full_name (klass);
10564 mono_error_set_type_load_class (error, klass, "Could not verify field '%s:%s' signature", full_name, field->name);;
10565 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
10566 g_free (full_name);
10570 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10572 mono_metadata_decode_value (sig, &sig);
10573 /* FIELD signature == 0x06 */
10574 g_assert (*sig == 0x06);
10576 ftype = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10578 char *full_name = mono_type_get_full_name (klass);
10579 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));
10580 g_free (full_name);
10583 mono_memory_barrier ();
10584 field->type = ftype;
10588 mono_field_resolve_flags (MonoClassField *field)
10590 MonoClass *klass = field->parent;
10591 MonoImage *image = klass->image;
10592 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10593 int field_idx = field - klass->fields;
10597 MonoClassField *gfield = >d->fields [field_idx];
10598 return mono_field_get_flags (gfield);
10600 int idx = mono_class_get_first_field_idx (klass) + field_idx;
10602 /*FIXME, in theory we do not lazy load SRE fields*/
10603 g_assert (!image_is_dynamic (image));
10605 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10610 * mono_class_get_fields_lazy:
10611 * @klass: the MonoClass to act on
10613 * This routine is an iterator routine for retrieving the fields in a class.
10614 * Only minimal information about fields are loaded. Accessors must be used
10615 * for all MonoClassField returned.
10617 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10618 * iterate over all of the elements. When no more values are
10619 * available, the return value is NULL.
10621 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10624 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10626 MonoClassField* field;
10630 mono_class_setup_basic_field_info (klass);
10631 if (!klass->fields)
10633 /* start from the first */
10634 if (mono_class_get_field_count (klass)) {
10635 *iter = &klass->fields [0];
10636 return (MonoClassField *)*iter;
10642 field = (MonoClassField *)*iter;
10644 if (field < &klass->fields [mono_class_get_field_count (klass)]) {
10646 return (MonoClassField *)*iter;
10652 mono_class_full_name (MonoClass *klass)
10654 return mono_type_full_name (&klass->byval_arg);
10657 /* Declare all shared lazy type lookup functions */
10658 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, System.Runtime.InteropServices, SafeHandle)