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 mono_loader_lock ();
1655 klass->instance_size = cached_info->instance_size;
1656 klass->sizes.class_size = cached_info->class_size;
1657 klass->packing_size = cached_info->packing_size;
1658 klass->min_align = cached_info->min_align;
1659 klass->blittable = cached_info->blittable;
1660 klass->has_references = cached_info->has_references;
1661 klass->has_static_refs = cached_info->has_static_refs;
1662 klass->no_special_static_fields = cached_info->no_special_static_fields;
1663 mono_loader_unlock ();
1666 if (!klass->size_inited)
1667 mono_class_setup_fields (klass);
1672 * mono_class_init_sizes:
1674 * Initializes the size related fields of @klass without loading all field data if possible.
1675 * Sets the following fields in @klass:
1677 * - sizes.class_size
1684 * Can fail the class.
1686 * LOCKING: Acquires the loader lock.
1689 mono_class_init_sizes (MonoClass *klass)
1691 MonoCachedClassInfo cached_info;
1692 gboolean has_cached_info;
1694 if (klass->size_inited)
1697 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
1699 init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
1703 * mono_type_get_basic_type_from_generic:
1706 * Returns a closed type corresponding to the possibly open type
1710 mono_type_get_basic_type_from_generic (MonoType *type)
1712 /* When we do generic sharing we let type variables stand for reference/primitive types. */
1713 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) &&
1714 (!type->data.generic_param->gshared_constraint || type->data.generic_param->gshared_constraint->type == MONO_TYPE_OBJECT))
1715 return &mono_defaults.object_class->byval_arg;
1720 class_has_references (MonoClass *klass)
1722 mono_class_init_sizes (klass);
1725 * has_references is not set if this is called recursively, but this is not a problem since this is only used
1726 * during field layout, and instance fields are initialized before static fields, and instance fields can't
1729 return klass->has_references;
1733 type_has_references (MonoClass *klass, MonoType *ftype)
1735 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (klass, ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && class_has_references (mono_class_from_mono_type (ftype)))))
1737 if (!ftype->byref && (ftype->type == MONO_TYPE_VAR || ftype->type == MONO_TYPE_MVAR)) {
1738 MonoGenericParam *gparam = ftype->data.generic_param;
1740 if (gparam->gshared_constraint)
1741 return class_has_references (mono_class_from_mono_type (gparam->gshared_constraint));
1747 * mono_class_layout_fields:
1749 * @base_instance_size: base instance size
1752 * This contains the common code for computing the layout of classes and sizes.
1753 * This should only be called from mono_class_setup_fields () and
1754 * typebuilder_setup_fields ().
1756 * LOCKING: Acquires the loader lock
1759 mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_size, gboolean sre)
1762 const int top = mono_class_get_field_count (klass);
1763 guint32 layout = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK;
1764 guint32 pass, passes, real_size;
1765 gboolean gc_aware_layout = FALSE;
1766 gboolean has_static_fields = FALSE;
1767 gboolean has_references = FALSE;
1768 gboolean has_static_refs = FALSE;
1769 MonoClassField *field;
1771 int instance_size = base_instance_size;
1772 int class_size, min_align;
1774 gboolean *fields_has_references;
1777 * We want to avoid doing complicated work inside locks, so we compute all the required
1778 * information and write it to @klass inside a lock.
1780 if (klass->fields_inited)
1783 if ((packing_size & 0xffffff00) != 0) {
1784 mono_class_set_type_load_failure (klass, "Could not load struct '%s' with packing size %d >= 256", klass->name, packing_size);
1788 if (klass->parent) {
1789 min_align = klass->parent->min_align;
1790 /* we use | since it may have been set already */
1791 has_references = klass->has_references | klass->parent->has_references;
1795 /* We can't really enable 16 bytes alignment until the GC supports it.
1796 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1797 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1798 Bug #506144 is an example of this issue.
1800 if (klass->simd_type)
1805 * When we do generic sharing we need to have layout
1806 * information for open generic classes (either with a generic
1807 * context containing type variables or with a generic
1808 * container), so we don't return in that case anymore.
1811 if (klass->enumtype) {
1812 for (i = 0; i < top; i++) {
1813 field = &klass->fields [i];
1814 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1815 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
1820 if (!mono_class_enum_basetype (klass)) {
1821 mono_class_set_type_load_failure (klass, "The enumeration's base type is invalid.");
1827 * Enable GC aware auto layout: in this mode, reference
1828 * fields are grouped together inside objects, increasing collector
1830 * Requires that all classes whose layout is known to native code be annotated
1831 * with [StructLayout (LayoutKind.Sequential)]
1832 * Value types have gc_aware_layout disabled by default, as per
1833 * what the default is for other runtimes.
1835 /* corlib is missing [StructLayout] directives in many places */
1836 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1837 if (!klass->valuetype)
1838 gc_aware_layout = TRUE;
1841 /* Compute klass->blittable */
1844 blittable = klass->parent->blittable;
1845 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(mono_is_corlib_image (klass->image) && !strcmp (klass->name_space, "System") && !strcmp (klass->name, "ValueType")) && top)
1847 for (i = 0; i < top; i++) {
1848 field = &klass->fields [i];
1850 if (mono_field_is_deleted (field))
1852 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1855 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1858 MonoClass *field_class = mono_class_from_mono_type (field->type);
1860 mono_class_setup_fields (field_class);
1861 if (mono_class_has_failure (field_class)) {
1862 MonoError field_error;
1863 mono_error_init (&field_error);
1864 mono_error_set_for_class_failure (&field_error, field_class);
1865 mono_class_set_type_load_failure (klass, "Could not set up field '%s' due to: %s", field->name, mono_error_get_message (&field_error));
1866 mono_error_cleanup (&field_error);
1870 if (!field_class || !field_class->blittable)
1874 if (klass->enumtype)
1875 blittable = klass->element_class->blittable;
1877 if (mono_class_has_failure (klass))
1879 if (klass == mono_defaults.string_class)
1882 /* Compute klass->has_references */
1884 * Process non-static fields first, since static fields might recursively
1885 * refer to the class itself.
1887 for (i = 0; i < top; i++) {
1890 field = &klass->fields [i];
1892 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1893 ftype = mono_type_get_underlying_type (field->type);
1894 ftype = mono_type_get_basic_type_from_generic (ftype);
1895 if (type_has_references (klass, ftype))
1896 has_references = TRUE;
1901 * Compute field layout and total size (not considering static fields)
1903 field_offsets = g_new0 (int, top);
1904 fields_has_references = g_new0 (gboolean, top);
1905 int first_field_idx = mono_class_has_static_metadata (klass) ? mono_class_get_first_field_idx (klass) : 0;
1907 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1908 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1909 if (gc_aware_layout)
1914 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1917 if (klass->parent) {
1918 mono_class_setup_fields (klass->parent);
1919 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Cannot initialize parent class"))
1921 real_size = klass->parent->instance_size;
1923 real_size = sizeof (MonoObject);
1926 for (pass = 0; pass < passes; ++pass) {
1927 for (i = 0; i < top; i++){
1932 field = &klass->fields [i];
1934 if (mono_field_is_deleted (field))
1936 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1939 ftype = mono_type_get_underlying_type (field->type);
1940 ftype = mono_type_get_basic_type_from_generic (ftype);
1941 if (gc_aware_layout) {
1942 fields_has_references [i] = type_has_references (klass, ftype);
1943 if (fields_has_references [i]) {
1952 if ((top == 1) && (instance_size == sizeof (MonoObject)) &&
1953 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1954 /* This field is a hack inserted by MCS to empty structures */
1958 size = mono_type_size (field->type, &align);
1960 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1961 align = packing_size ? MIN (packing_size, align): align;
1962 /* if the field has managed references, we need to force-align it
1965 if (type_has_references (klass, ftype))
1966 align = MAX (align, sizeof (gpointer));
1968 min_align = MAX (align, min_align);
1969 field_offsets [i] = real_size;
1971 field_offsets [i] += align - 1;
1972 field_offsets [i] &= ~(align - 1);
1974 /*TypeBuilders produce all sort of weird things*/
1975 g_assert (image_is_dynamic (klass->image) || field_offsets [i] > 0);
1976 real_size = field_offsets [i] + size;
1979 /* Make SIMD types as big as a SIMD register since they can be stored into using simd stores */
1980 if (klass->simd_type)
1981 real_size = MAX (real_size, sizeof (MonoObject) + 16);
1982 instance_size = MAX (real_size, instance_size);
1984 if (instance_size & (min_align - 1)) {
1985 instance_size += min_align - 1;
1986 instance_size &= ~(min_align - 1);
1990 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
1994 for (i = 0; i < top; i++) {
1999 field = &klass->fields [i];
2002 * There must be info about all the fields in a type if it
2003 * uses explicit layout.
2005 if (mono_field_is_deleted (field))
2007 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2010 size = mono_type_size (field->type, &align);
2011 align = packing_size ? MIN (packing_size, align): align;
2012 min_align = MAX (align, min_align);
2015 /* Already set by typebuilder_setup_fields () */
2016 field_offsets [i] = field->offset + sizeof (MonoObject);
2018 int idx = first_field_idx + i;
2020 mono_metadata_field_info (klass->image, idx, &offset, NULL, NULL);
2021 field_offsets [i] = offset + sizeof (MonoObject);
2023 ftype = mono_type_get_underlying_type (field->type);
2024 ftype = mono_type_get_basic_type_from_generic (ftype);
2025 if (type_has_references (klass, ftype)) {
2026 if (field_offsets [i] % sizeof (gpointer)) {
2027 mono_class_set_type_load_failure (klass, "Reference typed field '%s' has explicit offset that is not pointer-size aligned.", field->name);
2034 real_size = MAX (real_size, size + field_offsets [i]);
2037 if (klass->has_references) {
2038 ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
2040 /* Check for overlapping reference and non-reference fields */
2041 for (i = 0; i < top; i++) {
2044 field = &klass->fields [i];
2046 if (mono_field_is_deleted (field))
2048 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2050 ftype = mono_type_get_underlying_type (field->type);
2051 if (MONO_TYPE_IS_REFERENCE (ftype))
2052 ref_bitmap [field_offsets [i] / sizeof (gpointer)] = 1;
2054 for (i = 0; i < top; i++) {
2055 field = &klass->fields [i];
2057 if (mono_field_is_deleted (field))
2059 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2062 // FIXME: Too much code does this
2064 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field_offsets [i] / sizeof (gpointer)]) {
2065 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]);
2069 g_free (ref_bitmap);
2072 instance_size = MAX (real_size, instance_size);
2073 if (instance_size & (min_align - 1)) {
2074 instance_size += min_align - 1;
2075 instance_size &= ~(min_align - 1);
2081 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2083 * This leads to all kinds of problems with nested structs, so only
2084 * enable it when a MONO_DEBUG property is set.
2086 * For small structs, set min_align to at least the struct size to improve
2087 * performance, and since the JIT memset/memcpy code assumes this and generates
2088 * unaligned accesses otherwise. See #78990 for a testcase.
2090 if (mono_align_small_structs && top) {
2091 if (instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2092 min_align = MAX (min_align, instance_size - sizeof (MonoObject));
2096 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR)
2097 instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
2098 else if (klass->byval_arg.type == MONO_TYPE_PTR)
2099 instance_size = sizeof (MonoObject) + sizeof (gpointer);
2101 /* Publish the data */
2102 mono_loader_lock ();
2103 if (klass->instance_size && !klass->image->dynamic) {
2104 /* Might be already set using cached info */
2105 if (klass->instance_size != instance_size) {
2106 /* Emit info to help debugging */
2107 g_print ("%s\n", mono_class_full_name (klass));
2108 g_print ("%d %d %d %d\n", klass->instance_size, instance_size, klass->blittable, blittable);
2109 g_print ("%d %d %d %d\n", klass->has_references, has_references, klass->packing_size, packing_size);
2110 g_print ("%d %d\n", klass->min_align, min_align);
2111 for (i = 0; i < top; ++i) {
2112 field = &klass->fields [i];
2113 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
2114 printf (" %s %d %d %d\n", klass->fields [i].name, klass->fields [i].offset, field_offsets [i], fields_has_references [i]);
2117 g_assert (klass->instance_size == instance_size);
2119 klass->instance_size = instance_size;
2121 klass->blittable = blittable;
2122 klass->has_references = has_references;
2123 klass->packing_size = packing_size;
2124 klass->min_align = min_align;
2125 for (i = 0; i < top; ++i) {
2126 field = &klass->fields [i];
2127 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
2128 klass->fields [i].offset = field_offsets [i];
2131 mono_memory_barrier ();
2132 klass->size_inited = 1;
2133 mono_loader_unlock ();
2136 * Compute static field layout and size
2137 * Static fields can reference the class itself, so this has to be
2138 * done after instance_size etc. are initialized.
2141 for (i = 0; i < top; i++) {
2145 field = &klass->fields [i];
2147 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2149 if (mono_field_is_deleted (field))
2152 if (mono_type_has_exceptions (field->type)) {
2153 mono_class_set_type_load_failure (klass, "Field '%s' has an invalid type.", field->name);
2157 has_static_fields = TRUE;
2159 size = mono_type_size (field->type, &align);
2160 field_offsets [i] = class_size;
2161 /*align is always non-zero here*/
2162 field_offsets [i] += align - 1;
2163 field_offsets [i] &= ~(align - 1);
2164 class_size = field_offsets [i] + size;
2167 if (has_static_fields && class_size == 0)
2168 /* Simplify code which depends on class_size != 0 if the class has static fields */
2171 /* Compute klass->has_static_refs */
2172 has_static_refs = FALSE;
2173 for (i = 0; i < top; i++) {
2176 field = &klass->fields [i];
2178 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
2179 ftype = mono_type_get_underlying_type (field->type);
2180 ftype = mono_type_get_basic_type_from_generic (ftype);
2181 if (type_has_references (klass, ftype))
2182 has_static_refs = TRUE;
2186 /*valuetypes can't be neither bigger than 1Mb or empty. */
2187 if (klass->valuetype && (klass->instance_size <= 0 || klass->instance_size > (0x100000 + sizeof (MonoObject))))
2188 mono_class_set_type_load_failure (klass, "Value type instance size (%d) cannot be zero, negative, or bigger than 1Mb", klass->instance_size);
2190 /* Publish the data */
2191 mono_loader_lock ();
2193 klass->sizes.class_size = class_size;
2194 klass->has_static_refs = has_static_refs;
2195 for (i = 0; i < top; ++i) {
2196 field = &klass->fields [i];
2198 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2199 field->offset = field_offsets [i];
2202 mono_memory_barrier ();
2203 klass->fields_inited = 1;
2204 mono_loader_unlock ();
2206 g_free (field_offsets);
2207 g_free (fields_has_references);
2211 create_array_method (MonoClass *klass, const char *name, MonoMethodSignature *sig)
2215 method = (MonoMethod *) mono_image_alloc0 (klass->image, sizeof (MonoMethodPInvoke));
2216 method->klass = klass;
2217 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2218 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2219 method->signature = sig;
2220 method->name = name;
2223 if (name [0] == '.') {
2224 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2226 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2232 * mono_class_setup_methods:
2235 * Initializes the 'methods' array in CLASS.
2236 * Calling this method should be avoided if possible since it allocates a lot
2237 * of long-living MonoMethod structures.
2238 * Methods belonging to an interface are assigned a sequential slot starting
2241 * On failure this function sets klass->has_failure and stores a MonoErrorBoxed with details
2244 mono_class_setup_methods (MonoClass *klass)
2247 MonoMethod **methods;
2252 if (mono_class_is_ginst (klass)) {
2254 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2256 mono_class_init (gklass);
2257 if (!mono_class_has_failure (gklass))
2258 mono_class_setup_methods (gklass);
2259 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2262 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2263 count = mono_class_get_method_count (gklass);
2264 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * (count + 1));
2266 for (i = 0; i < count; i++) {
2267 methods [i] = mono_class_inflate_generic_method_full_checked (
2268 gklass->methods [i], klass, mono_class_get_context (klass), &error);
2269 if (!mono_error_ok (&error)) {
2270 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2271 mono_class_set_type_load_failure (klass, "Could not inflate method %s due to %s", method, mono_error_get_message (&error));
2274 mono_error_cleanup (&error);
2278 } else if (klass->rank) {
2280 MonoMethod *amethod;
2281 MonoMethodSignature *sig;
2282 int count_generic = 0, first_generic = 0;
2284 gboolean jagged_ctor = FALSE;
2286 count = 3 + (klass->rank > 1? 2: 1);
2288 mono_class_setup_interfaces (klass, &error);
2289 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2291 if (klass->rank == 1 && klass->element_class->rank) {
2296 if (klass->interface_count) {
2297 count_generic = generic_array_methods (klass);
2298 first_generic = count;
2299 count += klass->interface_count * count_generic;
2302 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * count);
2304 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2305 sig->ret = &mono_defaults.void_class->byval_arg;
2306 sig->pinvoke = TRUE;
2307 sig->hasthis = TRUE;
2308 for (i = 0; i < klass->rank; ++i)
2309 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2311 amethod = create_array_method (klass, ".ctor", sig);
2312 methods [method_num++] = amethod;
2313 if (klass->rank > 1) {
2314 sig = mono_metadata_signature_alloc (klass->image, klass->rank * 2);
2315 sig->ret = &mono_defaults.void_class->byval_arg;
2316 sig->pinvoke = TRUE;
2317 sig->hasthis = TRUE;
2318 for (i = 0; i < klass->rank * 2; ++i)
2319 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2321 amethod = create_array_method (klass, ".ctor", sig);
2322 methods [method_num++] = amethod;
2326 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2327 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2328 sig->ret = &mono_defaults.void_class->byval_arg;
2329 sig->pinvoke = TRUE;
2330 sig->hasthis = TRUE;
2331 for (i = 0; i < klass->rank + 1; ++i)
2332 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2333 amethod = create_array_method (klass, ".ctor", sig);
2334 methods [method_num++] = amethod;
2337 /* element Get (idx11, [idx2, ...]) */
2338 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2339 sig->ret = &klass->element_class->byval_arg;
2340 sig->pinvoke = TRUE;
2341 sig->hasthis = TRUE;
2342 for (i = 0; i < klass->rank; ++i)
2343 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2344 amethod = create_array_method (klass, "Get", sig);
2345 methods [method_num++] = amethod;
2346 /* element& Address (idx11, [idx2, ...]) */
2347 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2348 sig->ret = &klass->element_class->this_arg;
2349 sig->pinvoke = TRUE;
2350 sig->hasthis = TRUE;
2351 for (i = 0; i < klass->rank; ++i)
2352 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2353 amethod = create_array_method (klass, "Address", sig);
2354 methods [method_num++] = amethod;
2355 /* void Set (idx11, [idx2, ...], element) */
2356 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2357 sig->ret = &mono_defaults.void_class->byval_arg;
2358 sig->pinvoke = TRUE;
2359 sig->hasthis = TRUE;
2360 for (i = 0; i < klass->rank; ++i)
2361 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2362 sig->params [i] = &klass->element_class->byval_arg;
2363 amethod = create_array_method (klass, "Set", sig);
2364 methods [method_num++] = amethod;
2366 for (i = 0; i < klass->interface_count; i++)
2367 setup_generic_array_ifaces (klass, klass->interfaces [i], methods, first_generic + i * count_generic);
2368 } else if (mono_class_has_static_metadata (klass)) {
2370 int first_idx = mono_class_get_first_method_idx (klass);
2372 count = mono_class_get_method_count (klass);
2373 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * count);
2374 for (i = 0; i < count; ++i) {
2375 int idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_METHOD, first_idx + i + 1);
2376 methods [i] = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | idx, klass, NULL, &error);
2378 mono_class_set_type_load_failure (klass, "Could not load method %d due to %s", i, mono_error_get_message (&error));
2379 mono_error_cleanup (&error);
2383 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * 1);
2387 if (MONO_CLASS_IS_INTERFACE (klass)) {
2389 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2390 for (i = 0; i < count; ++i) {
2391 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2392 methods [i]->slot = slot++;
2396 mono_image_lock (klass->image);
2398 if (!klass->methods) {
2399 mono_class_set_method_count (klass, count);
2401 /* Needed because of the double-checking locking pattern */
2402 mono_memory_barrier ();
2404 klass->methods = methods;
2407 mono_image_unlock (klass->image);
2411 * mono_class_get_method_by_index:
2413 * Returns klass->methods [index], initializing klass->methods if neccesary.
2415 * LOCKING: Acquires the loader lock.
2418 mono_class_get_method_by_index (MonoClass *klass, int index)
2422 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
2423 /* Avoid calling setup_methods () if possible */
2424 if (gklass && !klass->methods) {
2427 m = mono_class_inflate_generic_method_full_checked (
2428 gklass->container_class->methods [index], klass, mono_class_get_context (klass), &error);
2429 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2431 * If setup_methods () is called later for this class, no duplicates are created,
2432 * since inflate_generic_method guarantees that only one instance of a method
2433 * is created for each context.
2436 mono_class_setup_methods (klass);
2437 g_assert (m == klass->methods [index]);
2441 mono_class_setup_methods (klass);
2442 if (mono_class_has_failure (klass)) /*FIXME do proper error handling*/
2444 g_assert (index >= 0 && index < mono_class_get_method_count (klass));
2445 return klass->methods [index];
2450 * mono_class_get_inflated_method:
2452 * Given an inflated class CLASS and a method METHOD which should be a method of
2453 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2456 mono_class_get_inflated_method (MonoClass *klass, MonoMethod *method)
2458 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2461 g_assert (method->klass == gklass);
2463 mono_class_setup_methods (gklass);
2464 g_assert (!mono_class_has_failure (gklass)); /*FIXME do proper error handling*/
2466 mcount = mono_class_get_method_count (gklass);
2467 for (i = 0; i < mcount; ++i) {
2468 if (gklass->methods [i] == method) {
2469 if (klass->methods) {
2470 return klass->methods [i];
2473 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], klass, mono_class_get_context (klass), &error);
2474 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2484 * mono_class_get_vtable_entry:
2486 * Returns klass->vtable [offset], computing it if neccesary. Returns NULL on failure.
2487 * LOCKING: Acquires the loader lock.
2490 mono_class_get_vtable_entry (MonoClass *klass, int offset)
2494 if (klass->rank == 1) {
2496 * szarrays do not overwrite any methods of Array, so we can avoid
2497 * initializing their vtables in some cases.
2499 mono_class_setup_vtable (klass->parent);
2500 if (offset < klass->parent->vtable_size)
2501 return klass->parent->vtable [offset];
2504 if (mono_class_is_ginst (klass)) {
2506 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2507 mono_class_setup_vtable (gklass);
2508 m = gklass->vtable [offset];
2510 m = mono_class_inflate_generic_method_full_checked (m, klass, mono_class_get_context (klass), &error);
2511 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2513 mono_class_setup_vtable (klass);
2514 if (mono_class_has_failure (klass))
2516 m = klass->vtable [offset];
2523 * mono_class_get_vtable_size:
2525 * Return the vtable size for KLASS.
2528 mono_class_get_vtable_size (MonoClass *klass)
2530 mono_class_setup_vtable (klass);
2532 return klass->vtable_size;
2536 * mono_class_setup_properties:
2538 * Initialize klass->ext.property and klass->ext.properties.
2540 * This method can fail the class.
2543 mono_class_setup_properties (MonoClass *klass)
2545 guint startm, endm, i, j;
2546 guint32 cols [MONO_PROPERTY_SIZE];
2547 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2548 MonoProperty *properties;
2551 MonoClassPropertyInfo *info;
2553 info = mono_class_get_property_info (klass);
2557 if (mono_class_is_ginst (klass)) {
2558 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2560 mono_class_init (gklass);
2561 mono_class_setup_properties (gklass);
2562 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2565 MonoClassPropertyInfo *ginfo = mono_class_get_property_info (gklass);
2566 properties = mono_class_new0 (klass, MonoProperty, ginfo->count + 1);
2568 for (i = 0; i < ginfo->count; i++) {
2570 MonoProperty *prop = &properties [i];
2572 *prop = ginfo->properties [i];
2575 prop->get = mono_class_inflate_generic_method_full_checked (
2576 prop->get, klass, mono_class_get_context (klass), &error);
2578 prop->set = mono_class_inflate_generic_method_full_checked (
2579 prop->set, klass, mono_class_get_context (klass), &error);
2581 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2582 prop->parent = klass;
2585 first = ginfo->first;
2586 count = ginfo->count;
2588 first = mono_metadata_properties_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2589 count = last - first;
2592 mono_class_setup_methods (klass);
2593 if (mono_class_has_failure (klass))
2597 properties = (MonoProperty *)mono_class_alloc0 (klass, sizeof (MonoProperty) * count);
2598 for (i = first; i < last; ++i) {
2599 mono_metadata_decode_table_row (klass->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2600 properties [i - first].parent = klass;
2601 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2602 properties [i - first].name = mono_metadata_string_heap (klass->image, cols [MONO_PROPERTY_NAME]);
2604 startm = mono_metadata_methods_from_property (klass->image, i, &endm);
2605 int first_idx = mono_class_get_first_method_idx (klass);
2606 for (j = startm; j < endm; ++j) {
2609 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2611 if (klass->image->uncompressed_metadata) {
2613 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2614 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2615 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2617 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - first_idx];
2620 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2621 case METHOD_SEMANTIC_SETTER:
2622 properties [i - first].set = method;
2624 case METHOD_SEMANTIC_GETTER:
2625 properties [i - first].get = method;
2634 info = mono_class_alloc0 (klass, sizeof (MonoClassPropertyInfo));
2635 info->first = first;
2636 info->count = count;
2637 info->properties = properties;
2638 mono_memory_barrier ();
2640 /* This might leak 'info' which was allocated from the image mempool */
2641 mono_class_set_property_info (klass, info);
2645 inflate_method_listz (MonoMethod **methods, MonoClass *klass, MonoGenericContext *context)
2647 MonoMethod **om, **retval;
2650 for (om = methods, count = 0; *om; ++om, ++count)
2653 retval = g_new0 (MonoMethod*, count + 1);
2655 for (om = methods, count = 0; *om; ++om, ++count) {
2657 retval [count] = mono_class_inflate_generic_method_full_checked (*om, klass, context, &error);
2658 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2664 /*This method can fail the class.*/
2666 mono_class_setup_events (MonoClass *klass)
2669 guint startm, endm, i, j;
2670 guint32 cols [MONO_EVENT_SIZE];
2671 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2675 MonoClassEventInfo *info = mono_class_get_event_info (klass);
2679 if (mono_class_is_ginst (klass)) {
2680 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2681 MonoGenericContext *context = NULL;
2683 mono_class_setup_events (gklass);
2684 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2687 MonoClassEventInfo *ginfo = mono_class_get_event_info (gklass);
2688 first = ginfo->first;
2689 count = ginfo->count;
2691 events = mono_class_new0 (klass, MonoEvent, count);
2694 context = mono_class_get_context (klass);
2696 for (i = 0; i < count; i++) {
2698 MonoEvent *event = &events [i];
2699 MonoEvent *gevent = &ginfo->events [i];
2701 mono_error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2703 event->parent = klass;
2704 event->name = gevent->name;
2705 event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, klass, context, &error) : NULL;
2706 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2707 event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, klass, context, &error) : NULL;
2708 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2709 event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, klass, context, &error) : NULL;
2710 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2712 #ifndef MONO_SMALL_CONFIG
2713 event->other = gevent->other ? inflate_method_listz (gevent->other, klass, context) : NULL;
2715 event->attrs = gevent->attrs;
2718 first = mono_metadata_events_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2719 count = last - first;
2722 mono_class_setup_methods (klass);
2723 if (mono_class_has_failure (klass)) {
2728 events = (MonoEvent *)mono_class_alloc0 (klass, sizeof (MonoEvent) * count);
2729 for (i = first; i < last; ++i) {
2730 MonoEvent *event = &events [i - first];
2732 mono_metadata_decode_table_row (klass->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2733 event->parent = klass;
2734 event->attrs = cols [MONO_EVENT_FLAGS];
2735 event->name = mono_metadata_string_heap (klass->image, cols [MONO_EVENT_NAME]);
2737 startm = mono_metadata_methods_from_event (klass->image, i, &endm);
2738 int first_idx = mono_class_get_first_method_idx (klass);
2739 for (j = startm; j < endm; ++j) {
2742 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2744 if (klass->image->uncompressed_metadata) {
2746 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2747 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2748 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2750 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - first_idx];
2753 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2754 case METHOD_SEMANTIC_ADD_ON:
2755 event->add = method;
2757 case METHOD_SEMANTIC_REMOVE_ON:
2758 event->remove = method;
2760 case METHOD_SEMANTIC_FIRE:
2761 event->raise = method;
2763 case METHOD_SEMANTIC_OTHER: {
2764 #ifndef MONO_SMALL_CONFIG
2767 if (event->other == NULL) {
2768 event->other = g_new0 (MonoMethod*, 2);
2770 while (event->other [n])
2772 event->other = (MonoMethod **)g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2774 event->other [n] = method;
2775 /* NULL terminated */
2776 event->other [n + 1] = NULL;
2787 info = mono_class_alloc0 (klass, sizeof (MonoClassEventInfo));
2788 info->events = events;
2789 info->first = first;
2790 info->count = count;
2792 mono_memory_barrier ();
2794 mono_class_set_event_info (klass, info);
2798 * Global pool of interface IDs, represented as a bitset.
2799 * LOCKING: Protected by the classes lock.
2801 static MonoBitSet *global_interface_bitset = NULL;
2804 * mono_unload_interface_ids:
2805 * @bitset: bit set of interface IDs
2807 * When an image is unloaded, the interface IDs associated with
2808 * the image are put back in the global pool of IDs so the numbers
2812 mono_unload_interface_ids (MonoBitSet *bitset)
2815 mono_bitset_sub (global_interface_bitset, bitset);
2820 mono_unload_interface_id (MonoClass *klass)
2822 if (global_interface_bitset && klass->interface_id) {
2824 mono_bitset_clear (global_interface_bitset, klass->interface_id);
2830 * mono_get_unique_iid:
2833 * Assign a unique integer ID to the interface represented by @class.
2834 * The ID will positive and as small as possible.
2835 * LOCKING: Acquires the classes lock.
2836 * Returns: The new ID.
2839 mono_get_unique_iid (MonoClass *klass)
2843 g_assert (MONO_CLASS_IS_INTERFACE (klass));
2847 if (!global_interface_bitset) {
2848 global_interface_bitset = mono_bitset_new (128, 0);
2851 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2853 int old_size = mono_bitset_size (global_interface_bitset);
2854 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2855 mono_bitset_free (global_interface_bitset);
2856 global_interface_bitset = new_set;
2859 mono_bitset_set (global_interface_bitset, iid);
2860 /* set the bit also in the per-image set */
2861 if (!mono_class_is_ginst (klass)) {
2862 if (klass->image->interface_bitset) {
2863 if (iid >= mono_bitset_size (klass->image->interface_bitset)) {
2864 MonoBitSet *new_set = mono_bitset_clone (klass->image->interface_bitset, iid + 1);
2865 mono_bitset_free (klass->image->interface_bitset);
2866 klass->image->interface_bitset = new_set;
2869 klass->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2871 mono_bitset_set (klass->image->interface_bitset, iid);
2876 #ifndef MONO_SMALL_CONFIG
2877 if (mono_print_vtable) {
2879 char *type_name = mono_type_full_name (&klass->byval_arg);
2880 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
2881 if (gklass && !gklass->context.class_inst->is_open) {
2882 generic_id = gklass->context.class_inst->id;
2883 g_assert (generic_id != 0);
2887 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, klass->image->name, type_name, generic_id);
2892 /* I've confirmed iids safe past 16 bits, however bitset code uses a signed int while testing.
2893 * Once this changes, it should be safe for us to allow 2^32-1 interfaces, until then 2^31-2 is the max. */
2894 g_assert (iid < INT_MAX);
2899 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, GHashTable **ifaces, MonoError *error)
2904 mono_class_setup_interfaces (klass, error);
2905 return_if_nok (error);
2907 for (i = 0; i < klass->interface_count; i++) {
2908 ic = klass->interfaces [i];
2911 *res = g_ptr_array_new ();
2912 if (*ifaces == NULL)
2913 *ifaces = g_hash_table_new (NULL, NULL);
2914 if (g_hash_table_lookup (*ifaces, ic))
2916 g_ptr_array_add (*res, ic);
2917 g_hash_table_insert (*ifaces, ic, ic);
2918 mono_class_init (ic);
2919 if (mono_class_has_failure (ic)) {
2920 mono_error_set_type_load_class (error, ic, "Error Loading class");
2924 collect_implemented_interfaces_aux (ic, res, ifaces, error);
2925 return_if_nok (error);
2930 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2932 GPtrArray *res = NULL;
2933 GHashTable *ifaces = NULL;
2935 collect_implemented_interfaces_aux (klass, &res, &ifaces, error);
2937 g_hash_table_destroy (ifaces);
2938 if (!mono_error_ok (error)) {
2940 g_ptr_array_free (res, TRUE);
2947 compare_interface_ids (const void *p_key, const void *p_element)
2949 const MonoClass *key = (const MonoClass *)p_key;
2950 const MonoClass *element = *(const MonoClass **)p_element;
2952 return (key->interface_id - element->interface_id);
2955 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2957 mono_class_interface_offset (MonoClass *klass, MonoClass *itf)
2959 MonoClass **result = (MonoClass **)mono_binary_search (
2961 klass->interfaces_packed,
2962 klass->interface_offsets_count,
2963 sizeof (MonoClass *),
2964 compare_interface_ids);
2966 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2973 * mono_class_interface_offset_with_variance:
2975 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2976 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2978 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2980 * FIXME figure out MS disambiguation rules and fix this function.
2983 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match)
2985 int i = mono_class_interface_offset (klass, itf);
2986 *non_exact_match = FALSE;
2990 if (itf->is_array_special_interface && klass->rank < 2) {
2991 MonoClass *gtd = mono_class_get_generic_type_definition (itf);
2993 for (i = 0; i < klass->interface_offsets_count; i++) {
2994 // printf ("\t%s\n", mono_type_get_full_name (klass->interfaces_packed [i]));
2995 if (mono_class_get_generic_type_definition (klass->interfaces_packed [i]) == gtd) {
2996 *non_exact_match = TRUE;
2997 return klass->interface_offsets_packed [i];
3002 if (!mono_class_has_variant_generic_params (itf))
3005 for (i = 0; i < klass->interface_offsets_count; i++) {
3006 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
3007 *non_exact_match = TRUE;
3008 return klass->interface_offsets_packed [i];
3016 print_implemented_interfaces (MonoClass *klass)
3020 GPtrArray *ifaces = NULL;
3022 int ancestor_level = 0;
3024 name = mono_type_get_full_name (klass);
3025 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
3028 for (i = 0; i < klass->interface_offsets_count; i++)
3029 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3030 klass->interfaces_packed [i]->interface_id,
3031 klass->interface_offsets_packed [i],
3032 mono_class_get_method_count (klass->interfaces_packed [i]),
3033 klass->interfaces_packed [i]->name_space,
3034 klass->interfaces_packed [i]->name );
3035 printf ("Interface flags: ");
3036 for (i = 0; i <= klass->max_interface_id; i++)
3037 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
3038 printf ("(%d,T)", i);
3040 printf ("(%d,F)", i);
3042 printf ("Dump interface flags:");
3043 #ifdef COMPRESSED_INTERFACE_BITMAP
3045 const uint8_t* p = klass->interface_bitmap;
3046 i = klass->max_interface_id;
3048 printf (" %d x 00 %02X", p [0], p [1]);
3054 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
3055 printf (" %02X", klass->interface_bitmap [i]);
3058 while (klass != NULL) {
3059 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
3060 ifaces = mono_class_get_implemented_interfaces (klass, &error);
3061 if (!mono_error_ok (&error)) {
3062 printf (" Type failed due to %s\n", mono_error_get_message (&error));
3063 mono_error_cleanup (&error);
3064 } else if (ifaces) {
3065 for (i = 0; i < ifaces->len; i++) {
3066 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3067 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
3068 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3070 mono_class_interface_offset (klass, ic),
3071 mono_class_get_method_count (ic),
3075 g_ptr_array_free (ifaces, TRUE);
3078 klass = klass->parent;
3083 * Return the number of virtual methods.
3084 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3085 * Return -1 on failure.
3086 * FIXME It would be nice if this information could be cached somewhere.
3089 count_virtual_methods (MonoClass *klass)
3091 int i, mcount, vcount = 0;
3093 klass = mono_class_get_generic_type_definition (klass); /*We can find this information by looking at the GTD*/
3095 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
3096 mono_class_setup_methods (klass);
3097 if (mono_class_has_failure (klass))
3100 mcount = mono_class_get_method_count (klass);
3101 for (i = 0; i < mcount; ++i) {
3102 flags = klass->methods [i]->flags;
3103 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3107 int first_idx = mono_class_get_first_method_idx (klass);
3108 mcount = mono_class_get_method_count (klass);
3109 for (i = 0; i < mcount; ++i) {
3110 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
3112 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3120 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3128 m = (l + num_ifaces) / 2;
3129 if (interfaces_full [m] == ic)
3131 if (l == num_ifaces)
3133 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3142 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3144 int i = find_interface (num_ifaces, interfaces_full, ic);
3148 interface_offsets_full [i] = offset;
3151 for (i = 0; i < num_ifaces; ++i) {
3152 if (interfaces_full [i]) {
3154 if (interfaces_full [i]->interface_id < ic->interface_id)
3157 while (end < num_ifaces && interfaces_full [end]) end++;
3158 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3159 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3161 interfaces_full [i] = ic;
3162 interface_offsets_full [i] = offset;
3168 #ifdef COMPRESSED_INTERFACE_BITMAP
3171 * Compressed interface bitmap design.
3173 * Interface bitmaps take a large amount of memory, because their size is
3174 * linear with the maximum interface id assigned in the process (each interface
3175 * is assigned a unique id as it is loaded). The number of interface classes
3176 * is high because of the many implicit interfaces implemented by arrays (we'll
3177 * need to lazy-load them in the future).
3178 * Most classes implement a very small number of interfaces, so the bitmap is
3179 * sparse. This bitmap needs to be checked by interface casts, so access to the
3180 * needed bit must be fast and doable with few jit instructions.
3182 * The current compression format is as follows:
3183 * *) it is a sequence of one or more two-byte elements
3184 * *) the first byte in the element is the count of empty bitmap bytes
3185 * at the current bitmap position
3186 * *) the second byte in the element is an actual bitmap byte at the current
3189 * As an example, the following compressed bitmap bytes:
3190 * 0x07 0x01 0x00 0x7
3191 * correspond to the following bitmap:
3192 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3194 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3195 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3196 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3200 * mono_compress_bitmap:
3201 * @dest: destination buffer
3202 * @bitmap: bitmap buffer
3203 * @size: size of @bitmap in bytes
3205 * This is a mono internal function.
3206 * The @bitmap data is compressed into a format that is small but
3207 * still searchable in few instructions by the JIT and runtime.
3208 * The compressed data is stored in the buffer pointed to by the
3209 * @dest array. Passing a #NULL value for @dest allows to just compute
3210 * the size of the buffer.
3211 * This compression algorithm assumes the bits set in the bitmap are
3212 * few and far between, like in interface bitmaps.
3213 * Returns: The size of the compressed bitmap in bytes.
3216 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3220 const uint8_t *end = bitmap + size;
3221 while (bitmap < end) {
3222 if (*bitmap || numz == 255) {
3246 * mono_class_interface_match:
3247 * @bitmap: a compressed bitmap buffer
3248 * @id: the index to check in the bitmap
3250 * This is a mono internal function.
3251 * Checks if a bit is set in a compressed interface bitmap. @id must
3252 * be already checked for being smaller than the maximum id encoded in the
3255 * Returns: A non-zero value if bit @id is set in the bitmap @bitmap,
3259 mono_class_interface_match (const uint8_t *bitmap, int id)
3262 id -= bitmap [0] * 8;
3266 return bitmap [1] & (1 << id);
3275 * Return -1 on failure and set klass->has_failure and store a MonoErrorBoxed with the details.
3276 * LOCKING: Acquires the loader lock.
3279 setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite)
3283 int i, j, num_ifaces;
3285 MonoClass **interfaces_full = NULL;
3286 int *interface_offsets_full = NULL;
3288 GPtrArray **ifaces_array = NULL;
3289 int interface_offsets_count;
3291 mono_loader_lock ();
3293 mono_class_setup_supertypes (klass);
3295 /* compute maximum number of slots and maximum interface id */
3297 num_ifaces = 0; /* this can include duplicated ones */
3298 ifaces_array = g_new0 (GPtrArray *, klass->idepth);
3299 for (j = 0; j < klass->idepth; j++) {
3300 k = klass->supertypes [j];
3302 num_ifaces += k->interface_count;
3303 for (i = 0; i < k->interface_count; i++) {
3304 ic = k->interfaces [i];
3306 mono_class_init (ic);
3308 if (max_iid < ic->interface_id)
3309 max_iid = ic->interface_id;
3311 ifaces = mono_class_get_implemented_interfaces (k, &error);
3312 if (!mono_error_ok (&error)) {
3313 char *name = mono_type_get_full_name (k);
3314 mono_class_set_type_load_failure (klass, "Error getting the interfaces of %s due to %s", name, mono_error_get_message (&error));
3316 mono_error_cleanup (&error);
3321 num_ifaces += ifaces->len;
3322 for (i = 0; i < ifaces->len; ++i) {
3323 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3324 if (max_iid < ic->interface_id)
3325 max_iid = ic->interface_id;
3327 ifaces_array [j] = ifaces;
3331 if (MONO_CLASS_IS_INTERFACE (klass)) {
3333 if (max_iid < klass->interface_id)
3334 max_iid = klass->interface_id;
3337 /* compute vtable offset for interfaces */
3338 interfaces_full = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3339 interface_offsets_full = (int *)g_malloc (sizeof (int) * num_ifaces);
3341 for (i = 0; i < num_ifaces; i++)
3342 interface_offsets_full [i] = -1;
3344 /* skip the current class */
3345 for (j = 0; j < klass->idepth - 1; j++) {
3346 k = klass->supertypes [j];
3347 ifaces = ifaces_array [j];
3350 for (i = 0; i < ifaces->len; ++i) {
3352 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3354 /*Force the sharing of interface offsets between parent and subtypes.*/
3355 io = mono_class_interface_offset (k, ic);
3357 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3362 g_assert (klass == klass->supertypes [klass->idepth - 1]);
3363 ifaces = ifaces_array [klass->idepth - 1];
3365 for (i = 0; i < ifaces->len; ++i) {
3367 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3368 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3370 count = count_virtual_methods (ic);
3372 char *name = mono_type_get_full_name (ic);
3373 mono_class_set_type_load_failure (klass, "Error calculating interface offset of %s", name);
3382 if (MONO_CLASS_IS_INTERFACE (klass))
3383 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, klass, cur_slot, TRUE);
3385 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3386 if (interface_offsets_full [i] != -1)
3387 interface_offsets_count ++;
3390 /* Publish the data */
3391 klass->max_interface_id = max_iid;
3393 * We might get called multiple times:
3394 * - mono_class_init ()
3395 * - mono_class_setup_vtable ().
3396 * - mono_class_setup_interface_offsets ().
3397 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3398 * means we have to overwrite those when called from other places (#4440).
3400 if (klass->interfaces_packed) {
3402 g_assert (klass->interface_offsets_count == interface_offsets_count);
3406 klass->interface_offsets_count = interface_offsets_count;
3407 klass->interfaces_packed = (MonoClass **)mono_class_alloc (klass, sizeof (MonoClass*) * interface_offsets_count);
3408 klass->interface_offsets_packed = (guint16 *)mono_class_alloc (klass, sizeof (guint16) * interface_offsets_count);
3409 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3410 #ifdef COMPRESSED_INTERFACE_BITMAP
3411 bitmap = g_malloc0 (bsize);
3413 bitmap = (uint8_t *)mono_class_alloc0 (klass, bsize);
3415 for (i = 0; i < interface_offsets_count; i++) {
3416 guint32 id = interfaces_full [i]->interface_id;
3417 bitmap [id >> 3] |= (1 << (id & 7));
3418 klass->interfaces_packed [i] = interfaces_full [i];
3419 klass->interface_offsets_packed [i] = interface_offsets_full [i];
3421 #ifdef COMPRESSED_INTERFACE_BITMAP
3422 i = mono_compress_bitmap (NULL, bitmap, bsize);
3423 klass->interface_bitmap = mono_class_alloc0 (klass, i);
3424 mono_compress_bitmap (klass->interface_bitmap, bitmap, bsize);
3427 klass->interface_bitmap = bitmap;
3431 mono_loader_unlock ();
3433 g_free (interfaces_full);
3434 g_free (interface_offsets_full);
3435 for (i = 0; i < klass->idepth; i++) {
3436 ifaces = ifaces_array [i];
3438 g_ptr_array_free (ifaces, TRUE);
3440 g_free (ifaces_array);
3442 //printf ("JUST DONE: ");
3443 //print_implemented_interfaces (klass);
3449 * Setup interface offsets for interfaces.
3451 * - klass->max_interface_id
3452 * - klass->interface_offsets_count
3453 * - klass->interfaces_packed
3454 * - klass->interface_offsets_packed
3455 * - klass->interface_bitmap
3457 * This function can fail @class.
3460 mono_class_setup_interface_offsets (MonoClass *klass)
3462 setup_interface_offsets (klass, 0, FALSE);
3465 /*Checks if @klass has @parent as one of it's parents type gtd
3469 * Bar<T> : Foo<Bar<Bar<T>>>
3473 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3475 klass = mono_class_get_generic_type_definition (klass);
3476 parent = mono_class_get_generic_type_definition (parent);
3477 mono_class_setup_supertypes (klass);
3478 mono_class_setup_supertypes (parent);
3480 return klass->idepth >= parent->idepth &&
3481 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3485 mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup)
3487 MonoGenericInst *ginst;
3490 if (!mono_class_is_ginst (klass)) {
3491 mono_class_setup_vtable_full (klass, in_setup);
3492 return !mono_class_has_failure (klass);
3495 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup);
3496 if (mono_class_set_type_load_failure_causedby_class (klass, mono_class_get_generic_class (klass)->container_class, "Failed to load generic definition vtable"))
3499 ginst = mono_class_get_generic_class (klass)->context.class_inst;
3500 for (i = 0; i < ginst->type_argc; ++i) {
3502 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3504 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3505 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3506 if (mono_class_has_gtd_parent (klass, arg) || mono_class_has_gtd_parent (arg, klass))
3508 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3509 mono_class_set_type_load_failure (klass, "Failed to load generic parameter %d", i);
3517 * mono_class_setup_vtable:
3519 * Creates the generic vtable of CLASS.
3520 * Initializes the following fields in MonoClass:
3523 * Plus all the fields initialized by setup_interface_offsets ().
3524 * If there is an error during vtable construction, klass->has_failure
3525 * is set and details are stored in a MonoErrorBoxed.
3527 * LOCKING: Acquires the loader lock.
3530 mono_class_setup_vtable (MonoClass *klass)
3532 mono_class_setup_vtable_full (klass, NULL);
3536 mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
3539 MonoMethod **overrides;
3540 MonoGenericContext *context;
3548 if (MONO_CLASS_IS_INTERFACE (klass)) {
3549 /* This sets method->slot for all methods if this is an interface */
3550 mono_class_setup_methods (klass);
3554 if (mono_class_has_failure (klass))
3557 if (g_list_find (in_setup, klass))
3560 mono_loader_lock ();
3562 if (klass->vtable) {
3563 mono_loader_unlock ();
3567 mono_stats.generic_vtable_count ++;
3568 in_setup = g_list_prepend (in_setup, klass);
3570 if (mono_class_is_ginst (klass)) {
3571 if (!mono_class_check_vtable_constraints (klass, in_setup)) {
3572 mono_loader_unlock ();
3573 g_list_remove (in_setup, klass);
3577 context = mono_class_get_context (klass);
3578 type_token = mono_class_get_generic_class (klass)->container_class->type_token;
3580 context = (MonoGenericContext *) mono_class_try_get_generic_container (klass); //FIXME is this a case of a try?
3581 type_token = klass->type_token;
3584 if (image_is_dynamic (klass->image)) {
3585 /* Generic instances can have zero method overrides without causing any harm.
3586 * This is true since we don't do layout all over again for them, we simply inflate
3587 * the layout of the parent.
3589 mono_reflection_get_dynamic_overrides (klass, &overrides, &onum, &error);
3590 if (!is_ok (&error)) {
3591 mono_loader_unlock ();
3592 g_list_remove (in_setup, klass);
3593 mono_class_set_type_load_failure (klass, "Could not load list of method overrides due to %s", mono_error_get_message (&error));
3594 mono_error_cleanup (&error);
3598 /* The following call fails if there are missing methods in the type */
3599 /* FIXME it's probably a good idea to avoid this for generic instances. */
3600 ok = mono_class_get_overrides_full (klass->image, type_token, &overrides, &onum, context);
3604 mono_class_setup_vtable_general (klass, overrides, onum, in_setup);
3606 mono_class_set_type_load_failure (klass, "Could not load list of method overrides");
3610 mono_loader_unlock ();
3611 g_list_remove (in_setup, klass);
3616 #define DEBUG_INTERFACE_VTABLE_CODE 0
3617 #define TRACE_INTERFACE_VTABLE_CODE 0
3618 #define VERIFY_INTERFACE_VTABLE_CODE 0
3619 #define VTABLE_SELECTOR (1)
3621 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3622 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3623 if (!(VTABLE_SELECTOR)) break; \
3627 #define DEBUG_INTERFACE_VTABLE(stmt)
3630 #if TRACE_INTERFACE_VTABLE_CODE
3631 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3632 if (!(VTABLE_SELECTOR)) break; \
3636 #define TRACE_INTERFACE_VTABLE(stmt)
3639 #if VERIFY_INTERFACE_VTABLE_CODE
3640 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3641 if (!(VTABLE_SELECTOR)) break; \
3645 #define VERIFY_INTERFACE_VTABLE(stmt)
3649 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3651 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3655 GString *res = g_string_new ("");
3657 g_string_append_c (res, '(');
3658 for (i = 0; i < sig->param_count; ++i) {
3660 g_string_append_c (res, ',');
3661 mono_type_get_desc (res, sig->params [i], include_namespace);
3663 g_string_append (res, ")=>");
3664 if (sig->ret != NULL) {
3665 mono_type_get_desc (res, sig->ret, include_namespace);
3667 g_string_append (res, "NULL");
3670 g_string_free (res, FALSE);
3674 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3675 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3676 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3677 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3685 is_wcf_hack_disabled (void)
3687 static gboolean disabled;
3688 static gboolean inited = FALSE;
3690 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3697 check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
3699 MonoMethodSignature *cmsig, *imsig;
3700 if (strcmp (im->name, cm->name) == 0) {
3701 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3702 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3705 if (! slot_is_empty) {
3706 if (require_newslot) {
3707 if (! interface_is_explicitly_implemented_by_class) {
3708 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3711 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3712 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3716 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3719 cmsig = mono_method_signature (cm);
3720 imsig = mono_method_signature (im);
3721 if (!cmsig || !imsig) {
3722 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
3726 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3727 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3728 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3729 TRACE_INTERFACE_VTABLE (printf ("]"));
3732 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3733 if (mono_security_core_clr_enabled ())
3734 mono_security_core_clr_check_override (klass, cm, im);
3736 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
3737 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3738 char *body_name = mono_method_full_name (cm, TRUE);
3739 char *decl_name = mono_method_full_name (im, TRUE);
3740 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
3748 MonoClass *ic = im->klass;
3749 const char *ic_name_space = ic->name_space;
3750 const char *ic_name = ic->name;
3753 if (! require_newslot) {
3754 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
3757 if (cm->klass->rank == 0) {
3758 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
3761 cmsig = mono_method_signature (cm);
3762 imsig = mono_method_signature (im);
3763 if (!cmsig || !imsig) {
3764 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
3768 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3769 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
3770 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3771 TRACE_INTERFACE_VTABLE (printf ("]"));
3774 if (mono_class_get_image (ic) != mono_defaults.corlib) {
3775 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
3778 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
3779 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
3782 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))) {
3783 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
3787 subname = strstr (cm->name, ic_name_space);
3788 if (subname != cm->name) {
3789 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
3792 subname += strlen (ic_name_space);
3793 if (subname [0] != '.') {
3794 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
3798 if (strstr (subname, ic_name) != subname) {
3799 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
3802 subname += strlen (ic_name);
3803 if (subname [0] != '.') {
3804 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
3808 if (strcmp (subname, im->name) != 0) {
3809 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
3813 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
3814 if (mono_security_core_clr_enabled ())
3815 mono_security_core_clr_check_override (klass, cm, im);
3817 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
3818 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3819 char *body_name = mono_method_full_name (cm, TRUE);
3820 char *decl_name = mono_method_full_name (im, TRUE);
3821 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
3831 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3833 foreach_override (gpointer key, gpointer value, gpointer user_data) {
3834 MonoMethod *method = key;
3835 MonoMethod *override = value;
3836 MonoClass *method_class = mono_method_get_class (method);
3837 MonoClass *override_class = mono_method_get_class (override);
3839 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
3840 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
3841 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
3844 print_overrides (GHashTable *override_map, const char *message) {
3846 printf ("Override map \"%s\" START:\n", message);
3847 g_hash_table_foreach (override_map, foreach_override, NULL);
3848 printf ("Override map \"%s\" END.\n", message);
3850 printf ("Override map \"%s\" EMPTY.\n", message);
3854 print_vtable_full (MonoClass *klass, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
3855 char *full_name = mono_type_full_name (&klass->byval_arg);
3859 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
3861 if (print_interfaces) {
3862 print_implemented_interfaces (klass);
3863 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
3866 if (klass->parent) {
3867 parent_size = klass->parent->vtable_size;
3871 for (i = 0; i < size; ++i) {
3872 MonoMethod *cm = vtable [i];
3873 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
3874 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
3876 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
3884 #if VERIFY_INTERFACE_VTABLE_CODE
3886 mono_method_try_get_vtable_index (MonoMethod *method)
3888 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
3889 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
3890 if (imethod->declaring->is_generic)
3891 return imethod->declaring->slot;
3893 return method->slot;
3897 mono_class_verify_vtable (MonoClass *klass)
3900 char *full_name = mono_type_full_name (&klass->byval_arg);
3902 printf ("*** Verifying VTable of class '%s' \n", full_name);
3906 if (!klass->methods)
3909 count = mono_class_method_count (klass);
3910 for (i = 0; i < count; ++i) {
3911 MonoMethod *cm = klass->methods [i];
3914 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
3918 full_name = mono_method_full_name (cm, TRUE);
3920 slot = mono_method_try_get_vtable_index (cm);
3922 if (slot >= klass->vtable_size) {
3923 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, klass->vtable_size);
3927 if (slot >= 0 && klass->vtable [slot] != cm && (klass->vtable [slot])) {
3928 char *other_name = klass->vtable [slot] ? mono_method_full_name (klass->vtable [slot], TRUE) : g_strdup ("[null value]");
3929 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
3930 g_free (other_name);
3933 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
3940 print_unimplemented_interface_method_info (MonoClass *klass, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum)
3943 char *method_signature;
3946 for (index = 0; index < onum; ++index) {
3947 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)", im_slot, overrides [index*2+1]->name,
3948 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
3950 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
3951 type_name = mono_type_full_name (&klass->byval_arg);
3952 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s",
3953 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
3954 g_free (method_signature);
3956 mono_class_setup_methods (klass);
3957 if (mono_class_has_failure (klass)) {
3958 char *name = mono_type_get_full_name (klass);
3959 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods", name);
3963 mcount = mono_class_get_method_count (klass);
3964 for (index = 0; index < mcount; ++index) {
3965 MonoMethod *cm = klass->methods [index];
3966 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
3968 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)", cm->name, method_signature);
3969 g_free (method_signature);
3974 mono_method_get_method_definition (MonoMethod *method)
3976 while (method->is_inflated)
3977 method = ((MonoMethodInflated*)method)->declaring;
3982 verify_class_overrides (MonoClass *klass, MonoMethod **overrides, int onum)
3986 for (i = 0; i < onum; ++i) {
3987 MonoMethod *decl = overrides [i * 2];
3988 MonoMethod *body = overrides [i * 2 + 1];
3990 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (klass)) {
3991 mono_class_set_type_load_failure (klass, "Method belongs to a different class than the declared one");
3995 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
3996 if (body->flags & METHOD_ATTRIBUTE_STATIC)
3997 mono_class_set_type_load_failure (klass, "Method must not be static to override a base type");
3999 mono_class_set_type_load_failure (klass, "Method must be virtual to override a base type");
4003 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4004 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4005 mono_class_set_type_load_failure (klass, "Cannot override a static method in a base type");
4007 mono_class_set_type_load_failure (klass, "Cannot override a non virtual method in a base type");
4011 if (!mono_class_is_assignable_from_slow (decl->klass, klass)) {
4012 mono_class_set_type_load_failure (klass, "Method overrides a class or interface that is not extended or implemented by this type");
4016 body = mono_method_get_method_definition (body);
4017 decl = mono_method_get_method_definition (decl);
4019 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4020 char *body_name = mono_method_full_name (body, TRUE);
4021 char *decl_name = mono_method_full_name (decl, TRUE);
4022 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4032 mono_class_need_stelemref_method (MonoClass *klass)
4034 return klass->rank == 1 && MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg);
4038 * LOCKING: this is supposed to be called with the loader lock held.
4041 mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int onum, GList *in_setup)
4045 MonoMethod **vtable = NULL;
4046 int i, max_vtsize = 0, cur_slot = 0;
4048 GPtrArray *ifaces = NULL;
4049 GHashTable *override_map = NULL;
4051 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4052 int first_non_interface_slot;
4054 GSList *virt_methods = NULL, *l;
4055 int stelemref_slot = 0;
4060 if (overrides && !verify_class_overrides (klass, overrides, onum))
4063 ifaces = mono_class_get_implemented_interfaces (klass, &error);
4064 if (!mono_error_ok (&error)) {
4065 char *name = mono_type_get_full_name (klass);
4066 mono_class_set_type_load_failure (klass, "Could not resolve %s interfaces due to %s", name, mono_error_get_message (&error));
4068 mono_error_cleanup (&error);
4070 } else if (ifaces) {
4071 for (i = 0; i < ifaces->len; i++) {
4072 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
4073 max_vtsize += mono_class_get_method_count (ic);
4075 g_ptr_array_free (ifaces, TRUE);
4079 if (klass->parent) {
4080 mono_class_init (klass->parent);
4081 mono_class_setup_vtable_full (klass->parent, in_setup);
4083 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class failed to load"))
4086 max_vtsize += klass->parent->vtable_size;
4087 cur_slot = klass->parent->vtable_size;
4090 max_vtsize += mono_class_get_method_count (klass);
4092 /*Array have a slot for stelemref*/
4093 if (mono_class_need_stelemref_method (klass)) {
4094 stelemref_slot = cur_slot;
4099 /* printf ("METAINIT %s.%s\n", klass->name_space, klass->name); */
4101 cur_slot = setup_interface_offsets (klass, cur_slot, TRUE);
4102 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4105 max_iid = klass->max_interface_id;
4106 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4108 /* Optimized version for generic instances */
4109 if (mono_class_is_ginst (klass)) {
4111 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4114 mono_class_setup_vtable_full (gklass, in_setup);
4115 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Could not load generic definition"))
4118 tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * gklass->vtable_size);
4119 klass->vtable_size = gklass->vtable_size;
4120 for (i = 0; i < gklass->vtable_size; ++i)
4121 if (gklass->vtable [i]) {
4122 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], klass, mono_class_get_context (klass), &error);
4123 if (!mono_error_ok (&error)) {
4124 mono_class_set_type_load_failure (klass, "Could not inflate method due to %s", mono_error_get_message (&error));
4125 mono_error_cleanup (&error);
4129 tmp [i]->slot = gklass->vtable [i]->slot;
4131 mono_memory_barrier ();
4132 klass->vtable = tmp;
4134 /* Have to set method->slot for abstract virtual methods */
4135 if (klass->methods && gklass->methods) {
4136 int mcount = mono_class_get_method_count (klass);
4137 for (i = 0; i < mcount; ++i)
4138 if (klass->methods [i]->slot == -1)
4139 klass->methods [i]->slot = gklass->methods [i]->slot;
4145 vtable = (MonoMethod **)g_malloc0 (sizeof (gpointer) * max_vtsize);
4147 if (klass->parent && klass->parent->vtable_size) {
4148 MonoClass *parent = klass->parent;
4151 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4153 // Also inherit parent interface vtables, just as a starting point.
4154 // This is needed otherwise bug-77127.exe fails when the property methods
4155 // have different names in the iterface and the class, because for child
4156 // classes the ".override" information is not used anymore.
4157 for (i = 0; i < parent->interface_offsets_count; i++) {
4158 MonoClass *parent_interface = parent->interfaces_packed [i];
4159 int interface_offset = mono_class_interface_offset (klass, parent_interface);
4160 /*FIXME this is now dead code as this condition will never hold true.
4161 Since interface offsets are inherited then the offset of an interface implemented
4162 by a parent will never be the out of it's vtable boundary.
4164 if (interface_offset >= parent->vtable_size) {
4165 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4168 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4169 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4170 int mcount = mono_class_get_method_count (parent_interface);
4171 for (j = 0; j < mcount && !mono_class_has_failure (klass); j++) {
4172 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4173 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4174 parent_interface_offset + j, parent_interface_offset, j,
4175 interface_offset + j, interface_offset, j));
4182 /*Array have a slot for stelemref*/
4183 if (mono_class_need_stelemref_method (klass)) {
4184 MonoMethod *method = mono_marshal_get_virtual_stelemref (klass);
4186 method->slot = stelemref_slot;
4188 g_assert (method->slot == stelemref_slot);
4190 vtable [stelemref_slot] = method;
4193 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4194 /* override interface methods */
4195 for (i = 0; i < onum; i++) {
4196 MonoMethod *decl = overrides [i*2];
4197 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4199 dslot = mono_method_get_vtable_slot (decl);
4201 mono_class_set_type_load_failure (klass, "");
4205 dslot += mono_class_interface_offset (klass, decl->klass);
4206 vtable [dslot] = overrides [i*2 + 1];
4207 vtable [dslot]->slot = dslot;
4209 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4211 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4213 if (mono_security_core_clr_enabled ())
4214 mono_security_core_clr_check_override (klass, vtable [dslot], decl);
4217 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4218 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4221 * Create a list of virtual methods to avoid calling
4222 * mono_class_get_virtual_methods () which is slow because of the metadata
4226 gpointer iter = NULL;
4229 virt_methods = NULL;
4230 while ((cm = mono_class_get_virtual_methods (klass, &iter))) {
4231 virt_methods = g_slist_prepend (virt_methods, cm);
4233 if (mono_class_has_failure (klass))
4237 // Loop on all implemented interfaces...
4238 for (i = 0; i < klass->interface_offsets_count; i++) {
4239 MonoClass *parent = klass->parent;
4241 gboolean interface_is_explicitly_implemented_by_class;
4244 ic = klass->interfaces_packed [i];
4245 ic_offset = mono_class_interface_offset (klass, ic);
4247 mono_class_setup_methods (ic);
4248 if (mono_class_has_failure (ic))
4251 // Check if this interface is explicitly implemented (instead of just inherited)
4252 if (parent != NULL) {
4253 int implemented_interfaces_index;
4254 interface_is_explicitly_implemented_by_class = FALSE;
4255 for (implemented_interfaces_index = 0; implemented_interfaces_index < klass->interface_count; implemented_interfaces_index++) {
4256 if (ic == klass->interfaces [implemented_interfaces_index]) {
4257 interface_is_explicitly_implemented_by_class = TRUE;
4262 interface_is_explicitly_implemented_by_class = TRUE;
4265 // Loop on all interface methods...
4266 int mcount = mono_class_get_method_count (ic);
4267 for (im_index = 0; im_index < mcount; im_index++) {
4268 MonoMethod *im = ic->methods [im_index];
4269 int im_slot = ic_offset + im->slot;
4270 MonoMethod *override_im = (override_map != NULL) ? (MonoMethod *)g_hash_table_lookup (override_map, im) : NULL;
4272 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4275 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4277 // If there is an explicit implementation, just use it right away,
4278 // otherwise look for a matching method
4279 if (override_im == NULL) {
4283 // First look for a suitable method among the class methods
4284 for (l = virt_methods; l; l = l->next) {
4285 cm = (MonoMethod *)l->data;
4286 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)));
4287 if (check_interface_method_override (klass, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
4288 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4289 vtable [im_slot] = cm;
4290 /* Why do we need this? */
4295 TRACE_INTERFACE_VTABLE (printf ("\n"));
4296 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4300 // If the slot is still empty, look in all the inherited virtual methods...
4301 if ((vtable [im_slot] == NULL) && klass->parent != NULL) {
4302 MonoClass *parent = klass->parent;
4303 // Reverse order, so that last added methods are preferred
4304 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4305 MonoMethod *cm = parent->vtable [cm_index];
4307 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));
4308 if ((cm != NULL) && check_interface_method_override (klass, im, cm, FALSE, FALSE, TRUE)) {
4309 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4310 vtable [im_slot] = cm;
4311 /* Why do we need this? */
4317 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4319 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4323 g_assert (vtable [im_slot] == override_im);
4328 // If the class is not abstract, check that all its interface slots are full.
4329 // The check is done here and not directly at the end of the loop above because
4330 // it can happen (for injected generic array interfaces) that the same slot is
4331 // processed multiple times (those interfaces have overlapping slots), and it
4332 // will not always be the first pass the one that fills the slot.
4333 if (!mono_class_is_abstract (klass)) {
4334 for (i = 0; i < klass->interface_offsets_count; i++) {
4338 ic = klass->interfaces_packed [i];
4339 ic_offset = mono_class_interface_offset (klass, ic);
4341 int mcount = mono_class_get_method_count (ic);
4342 for (im_index = 0; im_index < mcount; im_index++) {
4343 MonoMethod *im = ic->methods [im_index];
4344 int im_slot = ic_offset + im->slot;
4346 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4349 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4350 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4351 if (vtable [im_slot] == NULL) {
4352 print_unimplemented_interface_method_info (klass, ic, im, im_slot, overrides, onum);
4359 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4360 for (l = virt_methods; l; l = l->next) {
4361 cm = (MonoMethod *)l->data;
4363 * If the method is REUSE_SLOT, we must check in the
4364 * base class for a method to override.
4366 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4368 for (k = klass->parent; k ; k = k->parent) {
4373 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4374 MonoMethodSignature *cmsig, *m1sig;
4376 cmsig = mono_method_signature (cm);
4377 m1sig = mono_method_signature (m1);
4379 if (!cmsig || !m1sig) {
4380 /* FIXME proper error message */
4381 mono_class_set_type_load_failure (klass, "");
4385 if (!strcmp(cm->name, m1->name) &&
4386 mono_metadata_signature_equal (cmsig, m1sig)) {
4388 if (mono_security_core_clr_enabled ())
4389 mono_security_core_clr_check_override (klass, cm, m1);
4391 slot = mono_method_get_vtable_slot (m1);
4395 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4396 char *body_name = mono_method_full_name (cm, TRUE);
4397 char *decl_name = mono_method_full_name (m1, TRUE);
4398 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4404 g_assert (cm->slot < max_vtsize);
4406 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4407 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4408 mono_method_full_name (m1, 1), m1,
4409 mono_method_full_name (cm, 1), cm));
4410 g_hash_table_insert (override_map, m1, cm);
4414 if (mono_class_has_failure (k))
4424 /*Non final newslot methods must be given a non-interface vtable slot*/
4425 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4429 cm->slot = cur_slot++;
4431 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4432 vtable [cm->slot] = cm;
4435 /* override non interface methods */
4436 for (i = 0; i < onum; i++) {
4437 MonoMethod *decl = overrides [i*2];
4438 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4439 g_assert (decl->slot != -1);
4440 vtable [decl->slot] = overrides [i*2 + 1];
4441 overrides [i * 2 + 1]->slot = decl->slot;
4443 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4444 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4445 mono_method_full_name (decl, 1), decl,
4446 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4447 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4449 if (mono_security_core_clr_enabled ())
4450 mono_security_core_clr_check_override (klass, vtable [decl->slot], decl);
4455 * If a method occupies more than one place in the vtable, and it is
4456 * overriden, then change the other occurances too.
4461 for (i = 0; i < max_vtsize; ++i)
4463 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4465 cm = (MonoMethod *)g_hash_table_lookup (override_map, vtable [i]);
4470 g_hash_table_destroy (override_map);
4471 override_map = NULL;
4474 g_slist_free (virt_methods);
4475 virt_methods = NULL;
4477 g_assert (cur_slot <= max_vtsize);
4479 /* Ensure that all vtable slots are filled with concrete instance methods */
4480 if (!mono_class_is_abstract (klass)) {
4481 for (i = 0; i < cur_slot; ++i) {
4482 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4483 char *type_name = mono_type_get_full_name (klass);
4484 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4485 mono_class_set_type_load_failure (klass, "Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name);
4487 g_free (method_name);
4494 if (mono_class_is_ginst (klass)) {
4495 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4497 mono_class_init (gklass);
4499 klass->vtable_size = MAX (gklass->vtable_size, cur_slot);
4501 /* Check that the vtable_size value computed in mono_class_init () is correct */
4502 if (klass->vtable_size)
4503 g_assert (cur_slot == klass->vtable_size);
4504 klass->vtable_size = cur_slot;
4507 /* Try to share the vtable with our parent. */
4508 if (klass->parent && (klass->parent->vtable_size == klass->vtable_size) && (memcmp (klass->parent->vtable, vtable, sizeof (gpointer) * klass->vtable_size) == 0)) {
4509 mono_memory_barrier ();
4510 klass->vtable = klass->parent->vtable;
4512 MonoMethod **tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * klass->vtable_size);
4513 memcpy (tmp, vtable, sizeof (gpointer) * klass->vtable_size);
4514 mono_memory_barrier ();
4515 klass->vtable = tmp;
4518 DEBUG_INTERFACE_VTABLE (print_vtable_full (klass, klass->vtable, klass->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4519 if (mono_print_vtable) {
4522 print_implemented_interfaces (klass);
4524 for (i = 0; i <= max_iid; i++)
4525 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
4528 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&klass->byval_arg),
4529 klass->vtable_size, icount);
4531 for (i = 0; i < cur_slot; ++i) {
4536 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4537 mono_method_full_name (cm, TRUE));
4543 printf ("Interfaces %s.%s (max_iid = %d)\n", klass->name_space,
4544 klass->name, max_iid);
4546 for (i = 0; i < klass->interface_count; i++) {
4547 ic = klass->interfaces [i];
4548 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4549 mono_class_interface_offset (klass, ic),
4550 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4553 for (k = klass->parent; k ; k = k->parent) {
4554 for (i = 0; i < k->interface_count; i++) {
4555 ic = k->interfaces [i];
4556 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4557 mono_class_interface_offset (klass, ic),
4558 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4566 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (klass));
4571 char *name = mono_type_get_full_name (klass);
4572 mono_class_set_type_load_failure (klass, "VTable setup of type %s failed", name);
4576 g_hash_table_destroy (override_map);
4578 g_slist_free (virt_methods);
4583 * mono_method_get_vtable_slot:
4585 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4586 * LOCKING: Acquires the loader lock.
4588 * FIXME Use proper MonoError machinery here.
4591 mono_method_get_vtable_slot (MonoMethod *method)
4593 if (method->slot == -1) {
4594 mono_class_setup_vtable (method->klass);
4595 if (mono_class_has_failure (method->klass))
4597 if (method->slot == -1) {
4601 if (!mono_class_is_ginst (method->klass)) {
4602 g_assert (method->is_inflated);
4603 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4606 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4607 g_assert (mono_class_is_ginst (method->klass));
4608 gklass = mono_class_get_generic_class (method->klass)->container_class;
4609 mono_class_setup_methods (method->klass);
4610 g_assert (method->klass->methods);
4611 mcount = mono_class_get_method_count (method->klass);
4612 for (i = 0; i < mcount; ++i) {
4613 if (method->klass->methods [i] == method)
4616 g_assert (i < mcount);
4617 g_assert (gklass->methods);
4618 method->slot = gklass->methods [i]->slot;
4620 g_assert (method->slot != -1);
4622 return method->slot;
4626 * mono_method_get_vtable_index:
4629 * Returns the index into the runtime vtable to access the method or,
4630 * in the case of a virtual generic method, the virtual generic method
4631 * thunk. Returns -1 on failure.
4633 * FIXME Use proper MonoError machinery here.
4636 mono_method_get_vtable_index (MonoMethod *method)
4638 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4639 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4640 if (imethod->declaring->is_generic)
4641 return mono_method_get_vtable_slot (imethod->declaring);
4643 return mono_method_get_vtable_slot (method);
4646 static MonoMethod *default_ghc = NULL;
4647 static MonoMethod *default_finalize = NULL;
4648 static int finalize_slot = -1;
4649 static int ghc_slot = -1;
4652 initialize_object_slots (MonoClass *klass)
4657 if (klass == mono_defaults.object_class) {
4658 mono_class_setup_vtable (klass);
4659 for (i = 0; i < klass->vtable_size; ++i) {
4660 MonoMethod *cm = klass->vtable [i];
4662 if (!strcmp (cm->name, "GetHashCode"))
4664 else if (!strcmp (cm->name, "Finalize"))
4668 g_assert (ghc_slot > 0);
4669 default_ghc = klass->vtable [ghc_slot];
4671 g_assert (finalize_slot > 0);
4672 default_finalize = klass->vtable [finalize_slot];
4677 MonoMethod *array_method;
4679 } GenericArrayMethodInfo;
4681 static int generic_array_method_num = 0;
4682 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4685 generic_array_methods (MonoClass *klass)
4687 int i, count_generic = 0, mcount;
4688 GList *list = NULL, *tmp;
4689 if (generic_array_method_num)
4690 return generic_array_method_num;
4691 mono_class_setup_methods (klass->parent); /*This is setting up System.Array*/
4692 g_assert (!mono_class_has_failure (klass->parent)); /*So hitting this assert is a huge problem*/
4693 mcount = mono_class_get_method_count (klass->parent);
4694 for (i = 0; i < mcount; i++) {
4695 MonoMethod *m = klass->parent->methods [i];
4696 if (!strncmp (m->name, "InternalArray__", 15)) {
4698 list = g_list_prepend (list, m);
4701 list = g_list_reverse (list);
4702 generic_array_method_info = (GenericArrayMethodInfo *)mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4704 for (tmp = list; tmp; tmp = tmp->next) {
4705 const char *mname, *iname;
4707 MonoMethod *m = (MonoMethod *)tmp->data;
4708 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4709 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4711 generic_array_method_info [i].array_method = m;
4712 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4713 iname = "System.Collections.Generic.ICollection`1.";
4714 mname = m->name + 27;
4715 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4716 iname = "System.Collections.Generic.IEnumerable`1.";
4717 mname = m->name + 27;
4718 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4719 iname = "System.Collections.Generic.IReadOnlyList`1.";
4720 mname = m->name + strlen (ireadonlylist_prefix);
4721 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4722 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4723 mname = m->name + strlen (ireadonlycollection_prefix);
4724 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4725 iname = "System.Collections.Generic.IList`1.";
4726 mname = m->name + 15;
4728 g_assert_not_reached ();
4731 name = (gchar *)mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4732 strcpy (name, iname);
4733 strcpy (name + strlen (iname), mname);
4734 generic_array_method_info [i].name = name;
4737 /*g_print ("array generic methods: %d\n", count_generic);*/
4739 generic_array_method_num = count_generic;
4741 return generic_array_method_num;
4745 setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos)
4747 MonoGenericContext tmp_context;
4750 tmp_context.class_inst = NULL;
4751 tmp_context.method_inst = mono_class_get_generic_class (iface)->context.class_inst;
4752 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
4754 for (i = 0; i < generic_array_method_num; i++) {
4756 MonoMethod *m = generic_array_method_info [i].array_method;
4757 MonoMethod *inflated;
4759 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
4760 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
4761 methods [pos++] = mono_marshal_get_generic_array_helper (klass, iface, generic_array_method_info [i].name, inflated);
4766 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
4768 int null_length = strlen ("(null)");
4769 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
4770 char *s = (char *)mono_image_alloc (image, len);
4773 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
4774 g_assert (result == len - 1);
4781 * @klass: the class to initialize
4783 * Compute the instance_size, class_size and other infos that cannot be
4784 * computed at mono_class_get() time. Also compute vtable_size if possible.
4785 * Returns TRUE on success or FALSE if there was a problem in loading
4786 * the type (incorrect assemblies, missing assemblies, methods, etc).
4787 * Initializes the following fields in @klass:
4788 * - all the fields initialized by mono_class_init_sizes ()
4793 * LOCKING: Acquires the loader lock.
4796 mono_class_init (MonoClass *klass)
4798 int i, vtable_size = 0, array_method_count = 0;
4799 MonoCachedClassInfo cached_info;
4800 gboolean has_cached_info;
4801 gboolean locked = FALSE;
4802 gboolean ghcimpl = FALSE;
4803 gboolean has_cctor = FALSE;
4804 int first_iface_slot = 0;
4808 /* Double-checking locking pattern */
4809 if (klass->inited || mono_class_has_failure (klass))
4810 return !mono_class_has_failure (klass);
4812 /*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/
4815 * This function can recursively call itself.
4817 GSList *init_list = (GSList *)mono_native_tls_get_value (init_pending_tls_id);
4818 if (g_slist_find (init_list, klass)) {
4819 mono_class_set_type_load_failure (klass, "Recursive type definition detected");
4822 init_list = g_slist_prepend (init_list, klass);
4823 mono_native_tls_set_value (init_pending_tls_id, init_list);
4826 * We want to avoid doing complicated work inside locks, so we compute all the required
4827 * information and write it to @klass inside a lock.
4830 if (mono_verifier_is_enabled_for_class (klass) && !mono_verifier_verify_class (klass)) {
4831 mono_class_set_type_load_failure (klass, "%s", concat_two_strings_with_zero (klass->image, klass->name, klass->image->assembly_name));
4835 if (klass->byval_arg.type == MONO_TYPE_ARRAY || klass->byval_arg.type == MONO_TYPE_SZARRAY) {
4836 MonoClass *element_class = klass->element_class;
4837 if (!element_class->inited)
4838 mono_class_init (element_class);
4839 if (mono_class_set_type_load_failure_causedby_class (klass, element_class, "Could not load array element class"))
4843 mono_stats.initialized_class_count++;
4845 if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic) {
4846 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4848 mono_class_init (gklass);
4849 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic Type Definition failed to init"))
4852 mono_class_setup_interface_id (klass);
4855 if (klass->parent && !klass->parent->inited)
4856 mono_class_init (klass->parent);
4858 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
4860 /* Compute instance size etc. */
4861 init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
4862 if (mono_class_has_failure (klass))
4865 mono_class_setup_supertypes (klass);
4868 initialize_object_slots (klass);
4871 * Initialize the rest of the data without creating a generic vtable if possible.
4872 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
4873 * also avoid computing a generic vtable.
4875 if (has_cached_info) {
4877 vtable_size = cached_info.vtable_size;
4878 ghcimpl = cached_info.ghcimpl;
4879 has_cctor = cached_info.has_cctor;
4880 } else if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
4881 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
4882 * The first slot if for array with.
4884 static int szarray_vtable_size[2] = { 0 };
4886 int slot = MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg) ? 0 : 1;
4889 if (!szarray_vtable_size [slot]) {
4890 mono_class_setup_vtable (klass);
4891 szarray_vtable_size [slot] = klass->vtable_size;
4892 vtable_size = klass->vtable_size;
4894 vtable_size = szarray_vtable_size[slot];
4896 } else if (mono_class_is_ginst (klass) && !MONO_CLASS_IS_INTERFACE (klass)) {
4897 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4899 /* Generic instance case */
4900 ghcimpl = gklass->ghcimpl;
4901 has_cctor = gklass->has_cctor;
4903 mono_class_setup_vtable (gklass);
4904 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to init"))
4907 vtable_size = gklass->vtable_size;
4911 /* ghcimpl is not currently used
4913 if (klass->parent) {
4914 MonoMethod *cmethod = klass->vtable [ghc_slot];
4915 if (cmethod->is_inflated)
4916 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
4917 if (cmethod == default_ghc) {
4923 /* C# doesn't allow interfaces to have cctors */
4924 if (!MONO_CLASS_IS_INTERFACE (klass) || klass->image != mono_defaults.corlib) {
4925 MonoMethod *cmethod = NULL;
4927 if (mono_class_is_ginst (klass)) {
4928 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4930 /* Generic instance case */
4931 ghcimpl = gklass->ghcimpl;
4932 has_cctor = gklass->has_cctor;
4933 } else if (klass->type_token && !image_is_dynamic(klass->image)) {
4934 cmethod = find_method_in_metadata (klass, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
4935 /* The find_method function ignores the 'flags' argument */
4936 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
4939 mono_class_setup_methods (klass);
4940 if (mono_class_has_failure (klass))
4943 int mcount = mono_class_get_method_count (klass);
4944 for (i = 0; i < mcount; ++i) {
4945 MonoMethod *method = klass->methods [i];
4946 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
4947 (strcmp (".cctor", method->name) == 0)) {
4957 array_method_count = 3 + (klass->rank > 1? 2: 1);
4959 if (klass->interface_count) {
4960 int count_generic = generic_array_methods (klass);
4961 array_method_count += klass->interface_count * count_generic;
4965 if (klass->parent) {
4966 if (!klass->parent->vtable_size)
4967 mono_class_setup_vtable (klass->parent);
4968 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class vtable failed to initialize"))
4970 g_assert (klass->parent->vtable_size);
4971 first_iface_slot = klass->parent->vtable_size;
4972 if (mono_class_need_stelemref_method (klass))
4977 * Do the actual changes to @klass inside the loader lock
4979 mono_loader_lock ();
4982 if (klass->inited || mono_class_has_failure (klass)) {
4983 mono_loader_unlock ();
4984 /* Somebody might have gotten in before us */
4985 return !mono_class_has_failure (klass);
4988 mono_stats.initialized_class_count++;
4990 if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic)
4991 mono_stats.generic_class_count++;
4993 if (mono_class_is_ginst (klass) || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
4994 klass->nested_classes_inited = TRUE;
4995 klass->ghcimpl = ghcimpl;
4996 klass->has_cctor = has_cctor;
4998 klass->vtable_size = vtable_size;
4999 if (has_cached_info) {
5000 klass->has_finalize = cached_info.has_finalize;
5001 klass->has_finalize_inited = TRUE;
5004 mono_class_set_method_count (klass, array_method_count);
5006 mono_loader_unlock ();
5009 setup_interface_offsets (klass, first_iface_slot, TRUE);
5011 if (mono_security_core_clr_enabled ())
5012 mono_security_core_clr_check_inheritance (klass);
5014 if (mono_class_is_ginst (klass) && !mono_verifier_class_is_valid_generic_instantiation (klass))
5015 mono_class_set_type_load_failure (klass, "Invalid generic instantiation");
5020 init_list = g_slist_remove (init_list, klass);
5021 mono_native_tls_set_value (init_pending_tls_id, init_list);
5024 mono_loader_unlock ();
5026 /* Leave this for last */
5027 mono_loader_lock ();
5029 mono_loader_unlock ();
5031 return !mono_class_has_failure (klass);
5035 * mono_class_has_finalizer:
5037 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5041 mono_class_has_finalizer (MonoClass *klass)
5043 gboolean has_finalize = FALSE;
5045 if (klass->has_finalize_inited)
5046 return klass->has_finalize;
5048 /* Interfaces and valuetypes are not supposed to have finalizers */
5049 if (!(MONO_CLASS_IS_INTERFACE (klass) || klass->valuetype)) {
5050 MonoMethod *cmethod = NULL;
5052 if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5053 } else if (mono_class_is_ginst (klass)) {
5054 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5056 has_finalize = mono_class_has_finalizer (gklass);
5057 } else if (klass->parent && klass->parent->has_finalize) {
5058 has_finalize = TRUE;
5060 if (klass->parent) {
5062 * Can't search in metadata for a method named Finalize, because that
5063 * ignores overrides.
5065 mono_class_setup_vtable (klass);
5066 if (mono_class_has_failure (klass))
5069 cmethod = klass->vtable [finalize_slot];
5073 g_assert (klass->vtable_size > finalize_slot);
5075 if (klass->parent) {
5076 if (cmethod->is_inflated)
5077 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5078 if (cmethod != default_finalize)
5079 has_finalize = TRUE;
5085 mono_loader_lock ();
5086 if (!klass->has_finalize_inited) {
5087 klass->has_finalize = has_finalize ? 1 : 0;
5089 mono_memory_barrier ();
5090 klass->has_finalize_inited = TRUE;
5092 mono_loader_unlock ();
5094 return klass->has_finalize;
5098 mono_is_corlib_image (MonoImage *image)
5100 return image == mono_defaults.corlib;
5104 * LOCKING: this assumes the loader lock is held
5107 mono_class_setup_mono_type (MonoClass *klass)
5109 const char *name = klass->name;
5110 const char *nspace = klass->name_space;
5111 gboolean is_corlib = mono_is_corlib_image (klass->image);
5113 klass->this_arg.byref = 1;
5114 klass->this_arg.data.klass = klass;
5115 klass->this_arg.type = MONO_TYPE_CLASS;
5116 klass->byval_arg.data.klass = klass;
5117 klass->byval_arg.type = MONO_TYPE_CLASS;
5119 if (is_corlib && !strcmp (nspace, "System")) {
5120 if (!strcmp (name, "ValueType")) {
5122 * do not set the valuetype bit for System.ValueType.
5123 * klass->valuetype = 1;
5125 klass->blittable = TRUE;
5126 } else if (!strcmp (name, "Enum")) {
5128 * do not set the valuetype bit for System.Enum.
5129 * klass->valuetype = 1;
5131 klass->valuetype = 0;
5132 klass->enumtype = 0;
5133 } else if (!strcmp (name, "Object")) {
5134 klass->byval_arg.type = MONO_TYPE_OBJECT;
5135 klass->this_arg.type = MONO_TYPE_OBJECT;
5136 } else if (!strcmp (name, "String")) {
5137 klass->byval_arg.type = MONO_TYPE_STRING;
5138 klass->this_arg.type = MONO_TYPE_STRING;
5139 } else if (!strcmp (name, "TypedReference")) {
5140 klass->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5141 klass->this_arg.type = MONO_TYPE_TYPEDBYREF;
5145 if (klass->valuetype) {
5146 int t = MONO_TYPE_VALUETYPE;
5148 if (is_corlib && !strcmp (nspace, "System")) {
5151 if (!strcmp (name, "Boolean")) {
5152 t = MONO_TYPE_BOOLEAN;
5153 } else if (!strcmp(name, "Byte")) {
5155 klass->blittable = TRUE;
5159 if (!strcmp (name, "Char")) {
5164 if (!strcmp (name, "Double")) {
5166 klass->blittable = TRUE;
5170 if (!strcmp (name, "Int32")) {
5172 klass->blittable = TRUE;
5173 } else if (!strcmp(name, "Int16")) {
5175 klass->blittable = TRUE;
5176 } else if (!strcmp(name, "Int64")) {
5178 klass->blittable = TRUE;
5179 } else if (!strcmp(name, "IntPtr")) {
5181 klass->blittable = TRUE;
5185 if (!strcmp (name, "Single")) {
5187 klass->blittable = TRUE;
5188 } else if (!strcmp(name, "SByte")) {
5190 klass->blittable = TRUE;
5194 if (!strcmp (name, "UInt32")) {
5196 klass->blittable = TRUE;
5197 } else if (!strcmp(name, "UInt16")) {
5199 klass->blittable = TRUE;
5200 } else if (!strcmp(name, "UInt64")) {
5202 klass->blittable = TRUE;
5203 } else if (!strcmp(name, "UIntPtr")) {
5205 klass->blittable = TRUE;
5209 if (!strcmp (name, "TypedReference")) {
5210 t = MONO_TYPE_TYPEDBYREF;
5211 klass->blittable = TRUE;
5215 if (!strcmp (name, "Void")) {
5223 klass->byval_arg.type = (MonoTypeEnum)t;
5224 klass->this_arg.type = (MonoTypeEnum)t;
5227 if (MONO_CLASS_IS_INTERFACE (klass)) {
5228 klass->interface_id = mono_get_unique_iid (klass);
5230 if (is_corlib && !strcmp (nspace, "System.Collections.Generic")) {
5231 //FIXME IEnumerator needs to be special because GetEnumerator uses magic under the hood
5232 /* FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
5233 * MS returns diferrent types based on which instance is called. For example:
5234 * object obj = new byte[10][];
5235 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
5236 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
5239 if (!strcmp (name, "IList`1") || !strcmp (name, "ICollection`1") || !strcmp (name, "IEnumerable`1") || !strcmp (name, "IEnumerator`1"))
5240 klass->is_array_special_interface = 1;
5247 * COM initialization is delayed until needed.
5248 * However when a [ComImport] attribute is present on a type it will trigger
5249 * the initialization. This is not a problem unless the BCL being executed
5250 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5253 init_com_from_comimport (MonoClass *klass)
5255 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5256 if (mono_security_core_clr_enabled ()) {
5257 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5258 if (!mono_security_core_clr_determine_platform_image (klass->image)) {
5259 /* but it can not be made available for application (i.e. user code) since all COM calls
5260 * are considered native calls. In this case we fail with a TypeLoadException (just like
5261 * Silverlight 2 does */
5262 mono_class_set_type_load_failure (klass, "");
5267 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5269 #endif /*DISABLE_COM*/
5272 * LOCKING: this assumes the loader lock is held
5275 mono_class_setup_parent (MonoClass *klass, MonoClass *parent)
5277 gboolean system_namespace;
5278 gboolean is_corlib = mono_is_corlib_image (klass->image);
5280 system_namespace = !strcmp (klass->name_space, "System") && is_corlib;
5282 /* if root of the hierarchy */
5283 if (system_namespace && !strcmp (klass->name, "Object")) {
5284 klass->parent = NULL;
5285 klass->instance_size = sizeof (MonoObject);
5288 if (!strcmp (klass->name, "<Module>")) {
5289 klass->parent = NULL;
5290 klass->instance_size = 0;
5294 if (!MONO_CLASS_IS_INTERFACE (klass)) {
5295 /* Imported COM Objects always derive from __ComObject. */
5297 if (MONO_CLASS_IS_IMPORT (klass)) {
5298 init_com_from_comimport (klass);
5299 if (parent == mono_defaults.object_class)
5300 parent = mono_class_get_com_object_class ();
5304 /* set the parent to something useful and safe, but mark the type as broken */
5305 parent = mono_defaults.object_class;
5306 mono_class_set_type_load_failure (klass, "");
5310 klass->parent = parent;
5312 if (mono_class_is_ginst (parent) && !parent->name) {
5314 * If the parent is a generic instance, we may get
5315 * called before it is fully initialized, especially
5316 * before it has its name.
5321 #ifndef DISABLE_REMOTING
5322 klass->marshalbyref = parent->marshalbyref;
5323 klass->contextbound = parent->contextbound;
5326 klass->delegate = parent->delegate;
5328 if (MONO_CLASS_IS_IMPORT (klass) || mono_class_is_com_object (parent))
5329 mono_class_set_is_com_object (klass);
5331 if (system_namespace) {
5332 #ifndef DISABLE_REMOTING
5333 if (klass->name [0] == 'M' && !strcmp (klass->name, "MarshalByRefObject"))
5334 klass->marshalbyref = 1;
5336 if (klass->name [0] == 'C' && !strcmp (klass->name, "ContextBoundObject"))
5337 klass->contextbound = 1;
5339 if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate"))
5340 klass->delegate = 1;
5343 if (klass->parent->enumtype || (mono_is_corlib_image (klass->parent->image) && (strcmp (klass->parent->name, "ValueType") == 0) &&
5344 (strcmp (klass->parent->name_space, "System") == 0)))
5345 klass->valuetype = 1;
5346 if (mono_is_corlib_image (klass->parent->image) && ((strcmp (klass->parent->name, "Enum") == 0) && (strcmp (klass->parent->name_space, "System") == 0))) {
5347 klass->valuetype = klass->enumtype = 1;
5349 /*klass->enumtype = klass->parent->enumtype; */
5351 /* initialize com types if COM interfaces are present */
5353 if (MONO_CLASS_IS_IMPORT (klass))
5354 init_com_from_comimport (klass);
5356 klass->parent = NULL;
5362 * mono_class_setup_supertypes:
5365 * Build the data structure needed to make fast type checks work.
5366 * This currently sets two fields in @class:
5367 * - idepth: distance between @class and System.Object in the type
5369 * - supertypes: array of classes: each element has a class in the hierarchy
5370 * starting from @class up to System.Object
5372 * LOCKING: Acquires the loader lock.
5375 mono_class_setup_supertypes (MonoClass *klass)
5378 MonoClass **supertypes;
5380 mono_atomic_load_acquire (supertypes, MonoClass **, &klass->supertypes);
5384 if (klass->parent && !klass->parent->supertypes)
5385 mono_class_setup_supertypes (klass->parent);
5387 idepth = klass->parent->idepth + 1;
5391 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, idepth);
5392 supertypes = (MonoClass **)mono_class_alloc0 (klass, sizeof (MonoClass *) * ms);
5394 if (klass->parent) {
5395 CHECKED_METADATA_WRITE_PTR ( supertypes [idepth - 1] , klass );
5398 for (supertype_idx = 0; supertype_idx < klass->parent->idepth; supertype_idx++)
5399 CHECKED_METADATA_WRITE_PTR ( supertypes [supertype_idx] , klass->parent->supertypes [supertype_idx] );
5401 CHECKED_METADATA_WRITE_PTR ( supertypes [0] , klass );
5404 mono_memory_barrier ();
5406 mono_loader_lock ();
5407 klass->idepth = idepth;
5408 /* Needed so idepth is visible before supertypes is set */
5409 mono_memory_barrier ();
5410 klass->supertypes = supertypes;
5411 mono_loader_unlock ();
5415 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5417 MonoClass *gtd = (MonoClass*)user_data;
5418 /* Only try to fix generic instances of @gtd */
5419 if (mono_class_get_generic_class (gclass)->container_class != gtd)
5422 /* Check if the generic instance has no parent. */
5423 if (gtd->parent && !gclass->parent)
5424 mono_generic_class_setup_parent (gclass, gtd);
5430 mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char *msg)
5432 mono_class_set_type_load_failure (klass, "%s", msg);
5433 mono_error_set_type_load_class (error, klass, "%s", msg);
5437 * mono_class_create_from_typedef:
5438 * @image: image where the token is valid
5439 * @type_token: typedef token
5440 * @error: used to return any error found while creating the type
5442 * Create the MonoClass* representing the specified type token.
5443 * @type_token must be a TypeDef token.
5445 * FIXME: don't return NULL on failure, just the the caller figure it out.
5448 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5450 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5451 MonoClass *klass, *parent = NULL;
5452 guint32 cols [MONO_TYPEDEF_SIZE];
5453 guint32 cols_next [MONO_TYPEDEF_SIZE];
5454 guint tidx = mono_metadata_token_index (type_token);
5455 MonoGenericContext *context = NULL;
5456 const char *name, *nspace;
5458 MonoClass **interfaces;
5459 guint32 field_last, method_last;
5460 guint32 nesting_tokeen;
5462 mono_error_init (error);
5464 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5465 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5469 mono_loader_lock ();
5471 if ((klass = (MonoClass *)mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5472 mono_loader_unlock ();
5476 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5478 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5479 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5481 if (mono_metadata_has_generic_params (image, type_token)) {
5482 klass = mono_image_alloc0 (image, sizeof (MonoClassGtd));
5483 klass->class_kind = MONO_CLASS_GTD;
5484 classes_size += sizeof (MonoClassGtd);
5487 klass = mono_image_alloc0 (image, sizeof (MonoClassDef));
5488 klass->class_kind = MONO_CLASS_DEF;
5489 classes_size += sizeof (MonoClassDef);
5494 klass->name_space = nspace;
5496 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5498 klass->image = image;
5499 klass->type_token = type_token;
5500 mono_class_set_flags (klass, cols [MONO_TYPEDEF_FLAGS]);
5502 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
5505 * Check whether we're a generic type definition.
5507 if (mono_class_is_gtd (klass)) {
5508 MonoGenericContainer *generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
5509 generic_container->owner.klass = klass;
5510 generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
5511 context = &generic_container->context;
5512 mono_class_set_generic_container (klass, generic_container);
5513 enable_gclass_recording ();
5516 if (cols [MONO_TYPEDEF_EXTENDS]) {
5518 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5520 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5521 /*WARNING: this must satisfy mono_metadata_type_hash*/
5522 klass->this_arg.byref = 1;
5523 klass->this_arg.data.klass = klass;
5524 klass->this_arg.type = MONO_TYPE_CLASS;
5525 klass->byval_arg.data.klass = klass;
5526 klass->byval_arg.type = MONO_TYPE_CLASS;
5528 parent = mono_class_get_checked (image, parent_token, error);
5529 if (parent && context) /* Always inflate */
5530 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5532 if (parent == NULL) {
5533 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5534 goto parent_failure;
5537 for (tmp = parent; tmp; tmp = tmp->parent) {
5539 mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
5540 goto parent_failure;
5542 if (mono_class_is_gtd (klass) && mono_class_is_ginst (tmp) && mono_class_get_generic_class (tmp)->container_class == klass) {
5543 mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
5544 goto parent_failure;
5549 mono_class_setup_parent (klass, parent);
5551 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5552 mono_class_setup_mono_type (klass);
5554 if (mono_class_is_gtd (klass))
5555 disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
5558 * This might access klass->byval_arg for recursion generated by generic constraints,
5559 * so it has to come after setup_mono_type ().
5561 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5562 klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5563 if (!mono_error_ok (error)) {
5564 /*FIXME implement a mono_class_set_failure_from_mono_error */
5565 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5566 mono_loader_unlock ();
5567 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5572 if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5576 if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5580 klass->cast_class = klass->element_class = klass;
5581 if (mono_is_corlib_image (klass->image)) {
5582 switch (klass->byval_arg.type) {
5584 if (mono_defaults.byte_class)
5585 klass->cast_class = mono_defaults.byte_class;
5588 if (mono_defaults.sbyte_class)
5589 mono_defaults.sbyte_class = klass;
5592 if (mono_defaults.uint16_class)
5593 mono_defaults.uint16_class = klass;
5596 if (mono_defaults.int16_class)
5597 klass->cast_class = mono_defaults.int16_class;
5600 if (mono_defaults.uint32_class)
5601 mono_defaults.uint32_class = klass;
5604 if (mono_defaults.int32_class)
5605 klass->cast_class = mono_defaults.int32_class;
5608 if (mono_defaults.uint64_class)
5609 mono_defaults.uint64_class = klass;
5612 if (mono_defaults.int64_class)
5613 klass->cast_class = mono_defaults.int64_class;
5618 if (!klass->enumtype) {
5619 if (!mono_metadata_interfaces_from_typedef_full (
5620 image, type_token, &interfaces, &icount, FALSE, context, error)){
5622 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5623 mono_loader_unlock ();
5624 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5628 /* This is required now that it is possible for more than 2^16 interfaces to exist. */
5629 g_assert(icount <= 65535);
5631 klass->interfaces = interfaces;
5632 klass->interface_count = icount;
5633 klass->interfaces_inited = 1;
5636 /*g_print ("Load class %s\n", name);*/
5639 * Compute the field and method lists
5641 int first_field_idx = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5642 mono_class_set_first_field_idx (klass, first_field_idx);
5643 int first_method_idx = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5644 mono_class_set_first_method_idx (klass, first_method_idx);
5646 if (tt->rows > tidx){
5647 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5648 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5649 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5651 field_last = image->tables [MONO_TABLE_FIELD].rows;
5652 method_last = image->tables [MONO_TABLE_METHOD].rows;
5655 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5656 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5657 mono_class_set_field_count (klass, field_last - first_field_idx);
5658 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5659 mono_class_set_method_count (klass, method_last - first_method_idx);
5661 /* reserve space to store vector pointer in arrays */
5662 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5663 klass->instance_size += 2 * sizeof (gpointer);
5664 g_assert (mono_class_get_field_count (klass) == 0);
5667 if (klass->enumtype) {
5668 MonoType *enum_basetype = mono_class_find_enum_basetype (klass, error);
5669 if (!enum_basetype) {
5670 /*set it to a default value as the whole runtime can't handle this to be null*/
5671 klass->cast_class = klass->element_class = mono_defaults.int32_class;
5672 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5673 mono_loader_unlock ();
5674 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5677 klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
5681 * If we're a generic type definition, load the constraints.
5682 * We must do this after the class has been constructed to make certain recursive scenarios
5685 if (mono_class_is_gtd (klass) && !mono_metadata_load_generic_param_constraints_checked (image, type_token, mono_class_get_generic_container (klass), error)) {
5686 mono_class_set_type_load_failure (klass, "Could not load generic parameter constrains due to %s", mono_error_get_message (error));
5687 mono_loader_unlock ();
5688 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5692 if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5693 if (!strncmp (name, "Vector", 6))
5694 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");
5695 } else if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "System.Numerics") && !strcmp (nspace, "System.Numerics")) {
5696 if (!strcmp (name, "Vector2") || !strcmp (name, "Vector3") || !strcmp (name, "Vector4"))
5697 klass->simd_type = 1;
5700 mono_loader_unlock ();
5702 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5707 mono_class_setup_mono_type (klass);
5708 mono_loader_unlock ();
5709 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5713 /** Is klass a Nullable<T> ginst? */
5715 mono_class_is_nullable (MonoClass *klass)
5717 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
5718 return gklass && gklass->container_class == mono_defaults.generic_nullable_class;
5722 /** if klass is T? return T */
5724 mono_class_get_nullable_param (MonoClass *klass)
5726 g_assert (mono_class_is_nullable (klass));
5727 return mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
5731 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5735 MonoGenericClass *gclass = mono_class_get_generic_class (klass);
5737 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5738 if (!mono_error_ok (&error)) {
5739 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5740 klass->parent = mono_defaults.object_class;
5741 mono_class_set_type_load_failure (klass, "Parent is a generic type instantiation that failed due to: %s", mono_error_get_message (&error));
5742 mono_error_cleanup (&error);
5745 mono_loader_lock ();
5747 mono_class_setup_parent (klass, klass->parent);
5749 if (klass->enumtype) {
5750 klass->cast_class = gtd->cast_class;
5751 klass->element_class = gtd->element_class;
5753 mono_loader_unlock ();
5757 mono_type_is_primitive (MonoType *type)
5759 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
5760 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
5764 * Create the `MonoClass' for an instantiation of a generic type.
5765 * We only do this if we actually need it.
5768 mono_generic_class_get_class (MonoGenericClass *gclass)
5770 MonoClass *klass, *gklass;
5772 if (gclass->cached_class)
5773 return gclass->cached_class;
5775 klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClassGenericInst));
5777 gklass = gclass->container_class;
5779 if (gklass->nested_in) {
5780 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
5781 klass->nested_in = gklass->nested_in;
5784 klass->name = gklass->name;
5785 klass->name_space = gklass->name_space;
5787 klass->image = gklass->image;
5788 klass->type_token = gklass->type_token;
5790 klass->class_kind = MONO_CLASS_GINST;
5792 ((MonoClassGenericInst*)klass)->generic_class = gclass;
5794 klass->byval_arg.type = MONO_TYPE_GENERICINST;
5795 klass->this_arg.type = klass->byval_arg.type;
5796 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
5797 klass->this_arg.byref = TRUE;
5798 klass->enumtype = gklass->enumtype;
5799 klass->valuetype = gklass->valuetype;
5802 if (gklass->image->assembly_name && !strcmp (gklass->image->assembly_name, "System.Numerics.Vectors") && !strcmp (gklass->name_space, "System.Numerics") && !strcmp (gklass->name, "Vector`1")) {
5803 g_assert (gclass->context.class_inst);
5804 g_assert (gclass->context.class_inst->type_argc > 0);
5805 if (mono_type_is_primitive (gclass->context.class_inst->type_argv [0]))
5806 klass->simd_type = 1;
5808 klass->is_array_special_interface = gklass->is_array_special_interface;
5810 klass->cast_class = klass->element_class = klass;
5812 if (gclass->is_dynamic) {
5814 * 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.
5815 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
5816 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
5818 if (!gklass->wastypebuilder)
5821 if (klass->enumtype) {
5823 * For enums, gklass->fields might not been set, but instance_size etc. is
5824 * already set in mono_reflection_create_internal_class (). For non-enums,
5825 * these will be computed normally in mono_class_layout_fields ().
5827 klass->instance_size = gklass->instance_size;
5828 klass->sizes.class_size = gklass->sizes.class_size;
5829 klass->size_inited = 1;
5833 mono_loader_lock ();
5835 if (gclass->cached_class) {
5836 mono_loader_unlock ();
5837 return gclass->cached_class;
5840 if (record_gclass_instantiation > 0)
5841 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
5843 if (mono_class_is_nullable (klass))
5844 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
5846 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5848 mono_generic_class_setup_parent (klass, gklass);
5850 if (gclass->is_dynamic)
5851 mono_class_setup_supertypes (klass);
5853 mono_memory_barrier ();
5854 gclass->cached_class = klass;
5856 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5858 ++class_ginst_count;
5859 inflated_classes_size += sizeof (MonoClassGenericInst);
5861 mono_loader_unlock ();
5867 get_image_for_container (MonoGenericContainer *container)
5870 if (container->is_anonymous) {
5871 result = container->owner.image;
5874 if (container->is_method) {
5875 MonoMethod *method = container->owner.method;
5876 g_assert_checked (method);
5877 klass = method->klass;
5879 klass = container->owner.klass;
5881 g_assert_checked (klass);
5882 result = klass->image;
5889 get_image_for_generic_param (MonoGenericParam *param)
5891 MonoGenericContainer *container = mono_generic_param_owner (param);
5892 g_assert_checked (container);
5893 return get_image_for_container (container);
5896 // Make a string in the designated image consisting of a single integer.
5897 #define INT_STRING_SIZE 16
5899 make_generic_name_string (MonoImage *image, int num)
5901 char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
5902 g_snprintf (name, INT_STRING_SIZE, "%d", num);
5906 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
5907 // pinfo is derived from param by the caller for us.
5909 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
5911 MonoClass *klass, **ptr;
5913 MonoGenericContainer *container = mono_generic_param_owner (param);
5914 g_assert_checked (container);
5916 MonoImage *image = get_image_for_container (container);
5917 gboolean is_mvar = container->is_method;
5918 gboolean is_anonymous = container->is_anonymous;
5920 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassGenericParam));
5921 klass->class_kind = MONO_CLASS_GPARAM;
5922 classes_size += sizeof (MonoClassGenericParam);
5923 ++class_gparam_count;
5926 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
5928 int n = mono_generic_param_num (param);
5929 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
5933 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , "" );
5934 } else if (is_mvar) {
5935 MonoMethod *omethod = container->owner.method;
5936 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
5938 MonoClass *oklass = container->owner.klass;
5939 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
5942 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5944 // Count non-NULL items in pinfo->constraints
5947 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
5951 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
5952 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
5954 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
5955 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
5957 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
5960 if (count - pos > 0) {
5961 klass->interface_count = count - pos;
5962 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
5963 klass->interfaces_inited = TRUE;
5964 for (i = pos; i < count; i++)
5965 CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
5968 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
5970 klass->inited = TRUE;
5971 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class , klass );
5972 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
5974 klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
5975 klass->this_arg.type = klass->byval_arg.type;
5976 CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param , param );
5977 CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
5978 klass->this_arg.byref = TRUE;
5980 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
5981 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
5983 /*Init these fields to sane values*/
5984 klass->min_align = 1;
5986 * This makes sure the the value size of this class is equal to the size of the types the gparam is
5987 * constrained to, the JIT depends on this.
5989 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
5990 mono_memory_barrier ();
5991 klass->size_inited = 1;
5993 mono_class_setup_supertypes (klass);
5995 if (count - pos > 0) {
5996 mono_class_setup_vtable (klass->parent);
5997 if (mono_class_has_failure (klass->parent))
5998 mono_class_set_type_load_failure (klass, "Failed to setup parent interfaces");
6000 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6006 #define FAST_CACHE_SIZE 16
6009 * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6010 * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6011 * we cache the MonoClasses.
6012 * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6013 * LOCKING: Takes the image lock depending on @take_lock.
6016 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6018 int n = mono_generic_param_num (param);
6019 MonoImage *image = get_image_for_generic_param (param);
6020 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6021 MonoClass *klass = NULL;
6026 // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6027 // For high numbers or constraints we have to use pointer hashes.
6028 if (param->gshared_constraint) {
6029 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6032 mono_image_lock (image);
6033 klass = (MonoClass *)g_hash_table_lookup (ht, param);
6035 mono_image_unlock (image);
6040 if (n < FAST_CACHE_SIZE) {
6042 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6044 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6046 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6049 mono_image_lock (image);
6050 klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6052 mono_image_unlock (image);
6059 * LOCKING: Image lock (param->image) must be held
6062 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6064 int n = mono_generic_param_num (param);
6065 MonoImage *image = get_image_for_generic_param (param);
6066 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6070 if (param->gshared_constraint) {
6071 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6073 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6074 mono_memory_barrier ();
6076 image->mvar_cache_constrained = ht;
6078 image->var_cache_constrained = ht;
6080 g_hash_table_insert (ht, param, klass);
6081 } else if (n < FAST_CACHE_SIZE) {
6083 /* Requires locking to avoid droping an already published class */
6084 if (!image->mvar_cache_fast)
6085 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6086 image->mvar_cache_fast [n] = klass;
6088 if (!image->var_cache_fast)
6089 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6090 image->var_cache_fast [n] = klass;
6093 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6095 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6097 ht = g_hash_table_new (NULL, NULL);
6098 mono_memory_barrier ();
6100 image->mvar_cache_slow = ht;
6102 image->var_cache_slow = ht;
6105 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6110 * LOCKING: Acquires the image lock (@image).
6113 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6115 MonoImage *image = get_image_for_generic_param (param);
6116 MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6117 MonoClass *klass, *klass2;
6119 // If a klass already exists for this object and is cached, return it.
6120 if (pinfo) // Non-anonymous
6121 klass = pinfo->pklass;
6123 klass = get_anon_gparam_class (param, TRUE);
6128 // Create a new klass
6129 klass = make_generic_param_class (param, pinfo);
6131 // Now we need to cache the klass we created.
6132 // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6133 // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6134 // and allow our newly-created klass object to just leak.
6135 mono_memory_barrier ();
6137 mono_image_lock (image);
6139 // Here "klass2" refers to the klass potentially created by the other thread.
6140 if (pinfo) // Repeat check from above
6141 klass2 = pinfo->pklass;
6143 klass2 = get_anon_gparam_class (param, FALSE);
6150 pinfo->pklass = klass;
6152 set_anon_gparam_class (param, klass);
6154 mono_image_unlock (image);
6156 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6158 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED); // Alert profiler about botched class create
6160 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6166 * mono_class_from_generic_parameter:
6167 * @param: Parameter to find/construct a class for.
6168 * @arg2: Is ignored.
6169 * @arg3: Is ignored.
6172 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6174 return mono_class_from_generic_parameter_internal (param);
6178 mono_ptr_class_get (MonoType *type)
6181 MonoClass *el_class;
6185 el_class = mono_class_from_mono_type (type);
6186 image = el_class->image;
6188 mono_image_lock (image);
6189 if (image->ptr_cache) {
6190 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6191 mono_image_unlock (image);
6195 mono_image_unlock (image);
6197 result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassPointer));
6199 classes_size += sizeof (MonoClassPointer);
6200 ++class_pointer_count;
6202 result->parent = NULL; /* no parent for PTR types */
6203 result->name_space = el_class->name_space;
6204 name = g_strdup_printf ("%s*", el_class->name);
6205 result->name = mono_image_strdup (image, name);
6206 result->class_kind = MONO_CLASS_POINTER;
6209 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6211 result->image = el_class->image;
6212 result->inited = TRUE;
6213 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6214 result->cast_class = result->element_class = el_class;
6215 result->blittable = TRUE;
6217 result->byval_arg.type = MONO_TYPE_PTR;
6218 result->this_arg.type = result->byval_arg.type;
6219 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6220 result->this_arg.byref = TRUE;
6222 mono_class_setup_supertypes (result);
6224 mono_image_lock (image);
6225 if (image->ptr_cache) {
6227 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6228 mono_image_unlock (image);
6229 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6233 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6235 g_hash_table_insert (image->ptr_cache, el_class, result);
6236 mono_image_unlock (image);
6238 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6244 mono_fnptr_class_get (MonoMethodSignature *sig)
6246 MonoClass *result, *cached;
6247 static GHashTable *ptr_hash = NULL;
6249 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6251 mono_loader_lock ();
6253 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6254 cached = (MonoClass *)g_hash_table_lookup (ptr_hash, sig);
6255 mono_loader_unlock ();
6259 result = g_new0 (MonoClass, 1);
6261 result->parent = NULL; /* no parent for PTR types */
6262 result->name_space = "System";
6263 result->name = "MonoFNPtrFakeClass";
6264 result->class_kind = MONO_CLASS_POINTER;
6266 result->image = mono_defaults.corlib; /* need to fix... */
6267 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6268 result->cast_class = result->element_class = result;
6269 result->byval_arg.type = MONO_TYPE_FNPTR;
6270 result->this_arg.type = result->byval_arg.type;
6271 result->this_arg.data.method = result->byval_arg.data.method = sig;
6272 result->this_arg.byref = TRUE;
6273 result->blittable = TRUE;
6274 result->inited = TRUE;
6276 mono_class_setup_supertypes (result);
6278 mono_loader_lock ();
6280 cached = (MonoClass *)g_hash_table_lookup (ptr_hash, sig);
6283 mono_loader_unlock ();
6287 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6289 classes_size += sizeof (MonoClassPointer);
6290 ++class_pointer_count;
6292 g_hash_table_insert (ptr_hash, sig, result);
6294 mono_loader_unlock ();
6296 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6302 * mono_class_from_mono_type:
6303 * @type: describes the type to return
6305 * This returns a MonoClass for the specified MonoType, the value is never NULL.
6308 mono_class_from_mono_type (MonoType *type)
6310 switch (type->type) {
6311 case MONO_TYPE_OBJECT:
6312 return type->data.klass? type->data.klass: mono_defaults.object_class;
6313 case MONO_TYPE_VOID:
6314 return type->data.klass? type->data.klass: mono_defaults.void_class;
6315 case MONO_TYPE_BOOLEAN:
6316 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6317 case MONO_TYPE_CHAR:
6318 return type->data.klass? type->data.klass: mono_defaults.char_class;
6320 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6322 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6324 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6326 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6328 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6330 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6332 return type->data.klass? type->data.klass: mono_defaults.int_class;
6334 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6336 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6338 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6340 return type->data.klass? type->data.klass: mono_defaults.single_class;
6342 return type->data.klass? type->data.klass: mono_defaults.double_class;
6343 case MONO_TYPE_STRING:
6344 return type->data.klass? type->data.klass: mono_defaults.string_class;
6345 case MONO_TYPE_TYPEDBYREF:
6346 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6347 case MONO_TYPE_ARRAY:
6348 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6350 return mono_ptr_class_get (type->data.type);
6351 case MONO_TYPE_FNPTR:
6352 return mono_fnptr_class_get (type->data.method);
6353 case MONO_TYPE_SZARRAY:
6354 return mono_array_class_get (type->data.klass, 1);
6355 case MONO_TYPE_CLASS:
6356 case MONO_TYPE_VALUETYPE:
6357 return type->data.klass;
6358 case MONO_TYPE_GENERICINST:
6359 return mono_generic_class_get_class (type->data.generic_class);
6360 case MONO_TYPE_MVAR:
6362 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6364 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6365 g_assert_not_reached ();
6368 // Yes, this returns NULL, even if it is documented as not doing so, but there
6369 // is no way for the code to make it this far, due to the assert above.
6374 * mono_type_retrieve_from_typespec
6375 * @image: context where the image is created
6376 * @type_spec: typespec token
6377 * @context: the generic context used to evaluate generic instantiations in
6380 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6382 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6384 *did_inflate = FALSE;
6389 if (context && (context->class_inst || context->method_inst)) {
6390 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6392 if (!mono_error_ok (error)) {
6398 *did_inflate = TRUE;
6405 * mono_class_create_from_typespec
6406 * @image: context where the image is created
6407 * @type_spec: typespec token
6408 * @context: the generic context used to evaluate generic instantiations in
6411 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6414 gboolean inflated = FALSE;
6415 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6416 return_val_if_nok (error, NULL);
6417 ret = mono_class_from_mono_type (t);
6419 mono_metadata_free_type (t);
6424 * mono_bounded_array_class_get:
6425 * @element_class: element class
6426 * @rank: the dimension of the array class
6427 * @bounded: whenever the array has non-zero bounds
6429 * Returns: A class object describing the array with element type @element_type and
6433 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6436 MonoClass *klass, *cached, *k;
6437 MonoClass *parent = NULL;
6438 GSList *list, *rootlist = NULL;
6442 g_assert (rank <= 255);
6445 /* bounded only matters for one-dimensional arrays */
6448 image = eclass->image;
6452 if (rank == 1 && !bounded) {
6454 * This case is very frequent not just during compilation because of calls
6455 * from mono_class_from_mono_type (), mono_array_new (),
6456 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6458 mono_os_mutex_lock (&image->szarray_cache_lock);
6459 if (!image->szarray_cache)
6460 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6461 cached = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6462 mono_os_mutex_unlock (&image->szarray_cache_lock);
6464 mono_loader_lock ();
6465 if (!image->array_cache)
6466 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6467 rootlist = (GSList *)g_hash_table_lookup (image->array_cache, eclass);
6468 for (list = rootlist; list; list = list->next) {
6469 k = (MonoClass *)list->data;
6470 if ((k->rank == rank) && (k->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6475 mono_loader_unlock ();
6480 parent = mono_defaults.array_class;
6481 if (!parent->inited)
6482 mono_class_init (parent);
6484 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassArray));
6486 klass->image = image;
6487 klass->name_space = eclass->name_space;
6488 klass->class_kind = MONO_CLASS_ARRAY;
6490 nsize = strlen (eclass->name);
6491 name = (char *)g_malloc (nsize + 2 + rank + 1);
6492 memcpy (name, eclass->name, nsize);
6495 memset (name + nsize + 1, ',', rank - 1);
6497 name [nsize + rank] = '*';
6498 name [nsize + rank + bounded] = ']';
6499 name [nsize + rank + bounded + 1] = 0;
6500 klass->name = mono_image_strdup (image, name);
6503 klass->type_token = 0;
6504 klass->parent = parent;
6505 klass->instance_size = mono_class_instance_size (klass->parent);
6507 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6508 /*Arrays of those two types are invalid.*/
6509 MonoError prepared_error;
6510 mono_error_init (&prepared_error);
6511 mono_error_set_invalid_program (&prepared_error, "Arrays of void or System.TypedReference types are invalid.");
6512 mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6513 mono_error_cleanup (&prepared_error);
6514 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6515 guint32 ref_info_handle = mono_class_get_ref_info_handle (eclass);
6516 if (!ref_info_handle || eclass->wastypebuilder) {
6517 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6518 g_assert (ref_info_handle && !eclass->wastypebuilder);
6520 /* element_size -1 is ok as this is not an instantitable type*/
6521 klass->sizes.element_size = -1;
6523 klass->sizes.element_size = mono_class_array_element_size (eclass);
6525 mono_class_setup_supertypes (klass);
6527 if (mono_class_is_ginst (eclass))
6528 mono_class_init (eclass);
6529 if (!eclass->size_inited)
6530 mono_class_setup_fields (eclass);
6531 mono_class_set_type_load_failure_causedby_class (klass, eclass, "Could not load array element type");
6532 /*FIXME we fail the array type, but we have to let other fields be set.*/
6534 klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6538 if (eclass->enumtype)
6539 klass->cast_class = eclass->element_class;
6541 klass->cast_class = eclass;
6543 switch (klass->cast_class->byval_arg.type) {
6545 klass->cast_class = mono_defaults.byte_class;
6548 klass->cast_class = mono_defaults.int16_class;
6551 #if SIZEOF_VOID_P == 4
6555 klass->cast_class = mono_defaults.int32_class;
6558 #if SIZEOF_VOID_P == 8
6562 klass->cast_class = mono_defaults.int64_class;
6568 klass->element_class = eclass;
6570 if ((rank > 1) || bounded) {
6571 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6572 klass->byval_arg.type = MONO_TYPE_ARRAY;
6573 klass->byval_arg.data.array = at;
6574 at->eklass = eclass;
6576 /* FIXME: complete.... */
6578 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6579 klass->byval_arg.data.klass = eclass;
6581 klass->this_arg = klass->byval_arg;
6582 klass->this_arg.byref = 1;
6584 mono_loader_lock ();
6586 /* Check cache again */
6588 if (rank == 1 && !bounded) {
6589 mono_os_mutex_lock (&image->szarray_cache_lock);
6590 cached = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6591 mono_os_mutex_unlock (&image->szarray_cache_lock);
6593 rootlist = (GSList *)g_hash_table_lookup (image->array_cache, eclass);
6594 for (list = rootlist; list; list = list->next) {
6595 k = (MonoClass *)list->data;
6596 if ((k->rank == rank) && (k->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6603 mono_loader_unlock ();
6607 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6609 classes_size += sizeof (MonoClassArray);
6610 ++class_array_count;
6612 if (rank == 1 && !bounded) {
6613 mono_os_mutex_lock (&image->szarray_cache_lock);
6614 g_hash_table_insert (image->szarray_cache, eclass, klass);
6615 mono_os_mutex_unlock (&image->szarray_cache_lock);
6617 list = g_slist_append (rootlist, klass);
6618 g_hash_table_insert (image->array_cache, eclass, list);
6621 mono_loader_unlock ();
6623 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6629 * mono_array_class_get:
6630 * @element_class: element class
6631 * @rank: the dimension of the array class
6633 * Returns: A class object describing the array with element type @element_type and
6637 mono_array_class_get (MonoClass *eclass, guint32 rank)
6639 return mono_bounded_array_class_get (eclass, rank, FALSE);
6643 * mono_class_instance_size:
6646 * Use to get the size of a class in bytes.
6648 * Returns: The size of an object instance
6651 mono_class_instance_size (MonoClass *klass)
6653 if (!klass->size_inited)
6654 mono_class_init (klass);
6656 return klass->instance_size;
6660 * mono_class_min_align:
6663 * Use to get the computed minimum alignment requirements for the specified class.
6665 * Returns: minimum alignment requirements
6668 mono_class_min_align (MonoClass *klass)
6670 if (!klass->size_inited)
6671 mono_class_init (klass);
6673 return klass->min_align;
6677 * mono_class_value_size:
6680 * This function is used for value types, and return the
6681 * space and the alignment to store that kind of value object.
6683 * Returns: the size of a value of kind @klass
6686 mono_class_value_size (MonoClass *klass, guint32 *align)
6690 /* fixme: check disable, because we still have external revereces to
6691 * mscorlib and Dummy Objects
6693 /*g_assert (klass->valuetype);*/
6695 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6698 *align = klass->min_align;
6704 * mono_class_data_size:
6707 * Returns: The size of the static class data
6710 mono_class_data_size (MonoClass *klass)
6713 mono_class_init (klass);
6714 /* This can happen with dynamically created types */
6715 if (!klass->fields_inited)
6716 mono_class_setup_fields (klass);
6718 /* in arrays, sizes.class_size is unioned with element_size
6719 * and arrays have no static fields
6723 return klass->sizes.class_size;
6727 * Auxiliary routine to mono_class_get_field
6729 * Takes a field index instead of a field token.
6731 static MonoClassField *
6732 mono_class_get_field_idx (MonoClass *klass, int idx)
6734 mono_class_setup_fields (klass);
6735 if (mono_class_has_failure (klass))
6739 int first_field_idx = mono_class_get_first_field_idx (klass);
6740 int fcount = mono_class_get_field_count (klass);
6741 if (klass->image->uncompressed_metadata) {
6743 * first_field_idx points to the FieldPtr table, while idx points into the
6744 * Field table, so we have to do a search.
6746 /*FIXME this is broken for types with multiple fields with the same name.*/
6747 const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6750 for (i = 0; i < fcount; ++i)
6751 if (mono_field_get_name (&klass->fields [i]) == name)
6752 return &klass->fields [i];
6753 g_assert_not_reached ();
6756 if ((idx >= first_field_idx) && (idx < first_field_idx + fcount)){
6757 return &klass->fields [idx - first_field_idx];
6761 klass = klass->parent;
6767 * mono_class_get_field:
6768 * @class: the class to lookup the field.
6769 * @field_token: the field token
6771 * Returns: A MonoClassField representing the type and offset of
6772 * the field, or a NULL value if the field does not belong to this
6776 mono_class_get_field (MonoClass *klass, guint32 field_token)
6778 int idx = mono_metadata_token_index (field_token);
6780 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6782 return mono_class_get_field_idx (klass, idx - 1);
6786 * mono_class_get_field_from_name:
6787 * @klass: the class to lookup the field.
6788 * @name: the field name
6790 * Search the class @klass and it's parents for a field with the name @name.
6792 * Returns: The MonoClassField pointer of the named field or NULL
6795 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6797 return mono_class_get_field_from_name_full (klass, name, NULL);
6801 * mono_class_get_field_from_name_full:
6802 * @klass: the class to lookup the field.
6803 * @name: the field name
6804 * @type: the type of the fields. This optional.
6806 * Search the class @klass and it's parents for a field with the name @name and type @type.
6808 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
6809 * of its generic type definition.
6811 * Returns: The MonoClassField pointer of the named field or NULL
6814 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6818 mono_class_setup_fields (klass);
6819 if (mono_class_has_failure (klass))
6823 int fcount = mono_class_get_field_count (klass);
6824 for (i = 0; i < fcount; ++i) {
6825 MonoClassField *field = &klass->fields [i];
6827 if (strcmp (name, mono_field_get_name (field)) != 0)
6831 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6832 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6837 klass = klass->parent;
6843 * mono_class_get_field_token:
6844 * @field: the field we need the token of
6846 * Get the token of a field. Note that the tokesn is only valid for the image
6847 * the field was loaded from. Don't use this function for fields in dynamic types.
6849 * Returns: The token representing the field in the image it was loaded from.
6852 mono_class_get_field_token (MonoClassField *field)
6854 MonoClass *klass = field->parent;
6857 mono_class_setup_fields (klass);
6862 int first_field_idx = mono_class_get_first_field_idx (klass);
6863 int fcount = mono_class_get_field_count (klass);
6864 for (i = 0; i < fcount; ++i) {
6865 if (&klass->fields [i] == field) {
6866 int idx = first_field_idx + i + 1;
6868 if (klass->image->uncompressed_metadata)
6869 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
6870 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
6873 klass = klass->parent;
6876 g_assert_not_reached ();
6881 mono_field_get_index (MonoClassField *field)
6883 int index = field - field->parent->fields;
6884 g_assert (index >= 0 && index < mono_class_get_field_count (field->parent));
6890 * mono_class_get_field_default_value:
6892 * Return the default value of the field as a pointer into the metadata blob.
6895 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
6898 guint32 constant_cols [MONO_CONSTANT_SIZE];
6900 MonoClass *klass = field->parent;
6901 MonoFieldDefaultValue *def_values;
6903 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
6905 def_values = mono_class_get_field_def_values (klass);
6907 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
6909 mono_class_set_field_def_values (klass, def_values);
6912 field_index = mono_field_get_index (field);
6914 if (!def_values [field_index].data) {
6915 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
6919 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
6921 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
6922 def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
6923 mono_memory_barrier ();
6924 def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
6927 *def_type = def_values [field_index].def_type;
6928 return def_values [field_index].data;
6932 mono_property_get_index (MonoProperty *prop)
6934 MonoClassPropertyInfo *info = mono_class_get_property_info (prop->parent);
6935 int index = prop - info->properties;
6937 g_assert (index >= 0 && index < info->count);
6943 * mono_class_get_property_default_value:
6945 * Return the default value of the field as a pointer into the metadata blob.
6948 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
6951 guint32 constant_cols [MONO_CONSTANT_SIZE];
6952 MonoClass *klass = property->parent;
6954 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
6956 * We don't cache here because it is not used by C# so it's quite rare, but
6957 * we still do the lookup in klass->ext because that is where the data
6958 * is stored for dynamic assemblies.
6961 if (image_is_dynamic (klass->image)) {
6962 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
6963 int prop_index = mono_property_get_index (property);
6964 if (info->def_values && info->def_values [prop_index].data) {
6965 *def_type = info->def_values [prop_index].def_type;
6966 return info->def_values [prop_index].data;
6970 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
6974 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
6975 *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
6976 return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
6980 mono_class_get_event_token (MonoEvent *event)
6982 MonoClass *klass = event->parent;
6986 MonoClassEventInfo *info = mono_class_get_event_info (klass);
6988 for (i = 0; i < info->count; ++i) {
6989 if (&info->events [i] == event)
6990 return mono_metadata_make_token (MONO_TABLE_EVENT, info->first + i + 1);
6993 klass = klass->parent;
6996 g_assert_not_reached ();
7001 * mono_class_get_property_from_name:
7003 * @name: name of the property to lookup in the specified class
7005 * Use this method to lookup a property in a class
7006 * Returns: the MonoProperty with the given name, or NULL if the property
7007 * does not exist on the @klass.
7010 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7014 gpointer iter = NULL;
7015 while ((p = mono_class_get_properties (klass, &iter))) {
7016 if (! strcmp (name, p->name))
7019 klass = klass->parent;
7025 * mono_class_get_property_token:
7026 * @prop: MonoProperty to query
7028 * Returns: The ECMA token for the specified property.
7031 mono_class_get_property_token (MonoProperty *prop)
7033 MonoClass *klass = prop->parent;
7037 gpointer iter = NULL;
7038 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
7039 while ((p = mono_class_get_properties (klass, &iter))) {
7040 if (&info->properties [i] == prop)
7041 return mono_metadata_make_token (MONO_TABLE_PROPERTY, info->first + i + 1);
7045 klass = klass->parent;
7048 g_assert_not_reached ();
7053 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7055 const char *name, *nspace;
7056 if (image_is_dynamic (image))
7057 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7059 switch (type_token & 0xff000000){
7060 case MONO_TOKEN_TYPE_DEF: {
7061 guint32 cols [MONO_TYPEDEF_SIZE];
7062 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7063 guint tidx = mono_metadata_token_index (type_token);
7065 if (tidx > tt->rows)
7066 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7068 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7069 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7070 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7071 if (strlen (nspace) == 0)
7072 return g_strdup_printf ("%s", name);
7074 return g_strdup_printf ("%s.%s", nspace, name);
7077 case MONO_TOKEN_TYPE_REF: {
7079 guint32 cols [MONO_TYPEREF_SIZE];
7080 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7081 guint tidx = mono_metadata_token_index (type_token);
7084 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7086 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7087 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7088 mono_error_cleanup (&error);
7092 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7093 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7094 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7095 if (strlen (nspace) == 0)
7096 return g_strdup_printf ("%s", name);
7098 return g_strdup_printf ("%s.%s", nspace, name);
7101 case MONO_TOKEN_TYPE_SPEC:
7102 return g_strdup_printf ("Typespec 0x%08x", type_token);
7104 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7109 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7111 if (image_is_dynamic (image))
7112 return g_strdup_printf ("DynamicAssembly %s", image->name);
7114 switch (type_token & 0xff000000){
7115 case MONO_TOKEN_TYPE_DEF:
7116 if (image->assembly)
7117 return mono_stringify_assembly_name (&image->assembly->aname);
7118 else if (image->assembly_name)
7119 return g_strdup (image->assembly_name);
7120 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7121 case MONO_TOKEN_TYPE_REF: {
7123 MonoAssemblyName aname;
7124 guint32 cols [MONO_TYPEREF_SIZE];
7125 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7126 guint32 idx = mono_metadata_token_index (type_token);
7129 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7131 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7132 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7133 mono_error_cleanup (&error);
7136 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7138 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7139 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7140 case MONO_RESOLUTION_SCOPE_MODULE:
7142 return g_strdup ("");
7143 case MONO_RESOLUTION_SCOPE_MODULEREF:
7145 return g_strdup ("");
7146 case MONO_RESOLUTION_SCOPE_TYPEREF:
7148 return g_strdup ("");
7149 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7150 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7151 return mono_stringify_assembly_name (&aname);
7153 g_assert_not_reached ();
7157 case MONO_TOKEN_TYPE_SPEC:
7159 return g_strdup ("");
7161 g_assert_not_reached ();
7168 * mono_class_get_full:
7169 * @image: the image where the class resides
7170 * @type_token: the token for the class
7171 * @context: the generic context used to evaluate generic instantiations in
7172 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7174 * Returns: The MonoClass that represents @type_token in @image
7177 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7181 klass = mono_class_get_checked (image, type_token, &error);
7183 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7184 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7186 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7192 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7196 mono_error_init (error);
7197 klass = mono_class_get_checked (image, type_token, error);
7199 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7200 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7205 * mono_class_get_checked:
7206 * @image: the image where the class resides
7207 * @type_token: the token for the class
7208 * @error: error object to return any error
7210 * Returns: The MonoClass that represents @type_token in @image, or NULL on error.
7213 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7215 MonoClass *klass = NULL;
7217 mono_error_init (error);
7219 if (image_is_dynamic (image)) {
7220 int table = mono_metadata_token_table (type_token);
7222 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7223 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7226 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
7230 switch (type_token & 0xff000000){
7231 case MONO_TOKEN_TYPE_DEF:
7232 klass = mono_class_create_from_typedef (image, type_token, error);
7234 case MONO_TOKEN_TYPE_REF:
7235 klass = mono_class_from_typeref_checked (image, type_token, error);
7237 case MONO_TOKEN_TYPE_SPEC:
7238 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7241 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7245 /* Generic case, should be avoided for when a better error is possible. */
7246 if (!klass && mono_error_ok (error)) {
7247 char *name = mono_class_name_from_token (image, type_token);
7248 char *assembly = mono_assembly_name_from_token (image, type_token);
7249 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7257 * mono_type_get_checked:
7258 * @image: the image where the type resides
7259 * @type_token: the token for the type
7260 * @context: the generic context used to evaluate generic instantiations in
7261 * @error: Error handling context
7263 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7265 * Returns: The MonoType that represents @type_token in @image
7268 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7270 MonoType *type = NULL;
7271 gboolean inflated = FALSE;
7273 mono_error_init (error);
7275 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7276 if (image_is_dynamic (image)) {
7277 MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
7278 return_val_if_nok (error, NULL);
7279 return mono_class_get_type (klass);
7282 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7283 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7290 return mono_class_get_type (klass);
7293 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7300 MonoType *tmp = type;
7301 type = mono_class_get_type (mono_class_from_mono_type (type));
7302 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7303 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7304 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7306 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7308 if (type->type != tmp->type)
7311 mono_metadata_free_type (tmp);
7318 * @image: image where the class token will be looked up.
7319 * @type_token: a type token from the image
7321 * Returns the MonoClass with the given @type_token on the @image
7324 mono_class_get (MonoImage *image, guint32 type_token)
7326 return mono_class_get_full (image, type_token, NULL);
7330 * mono_image_init_name_cache:
7332 * Initializes the class name cache stored in image->name_cache.
7334 * LOCKING: Acquires the corresponding image lock.
7337 mono_image_init_name_cache (MonoImage *image)
7339 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7340 guint32 cols [MONO_TYPEDEF_SIZE];
7343 guint32 i, visib, nspace_index;
7344 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7346 if (image->name_cache)
7349 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7351 if (image_is_dynamic (image)) {
7352 mono_image_lock (image);
7353 if (image->name_cache) {
7354 /* Somebody initialized it before us */
7355 g_hash_table_destroy (the_name_cache);
7357 mono_atomic_store_release (&image->name_cache, the_name_cache);
7359 mono_image_unlock (image);
7363 /* Temporary hash table to avoid lookups in the nspace_table */
7364 name_cache2 = g_hash_table_new (NULL, NULL);
7366 for (i = 1; i <= t->rows; ++i) {
7367 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7368 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7370 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7371 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7373 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7375 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7376 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7378 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7379 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7380 if (!nspace_table) {
7381 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7382 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7383 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7386 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7389 /* Load type names from EXPORTEDTYPES table */
7391 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7392 guint32 cols [MONO_EXP_TYPE_SIZE];
7395 for (i = 0; i < t->rows; ++i) {
7396 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7398 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7399 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7403 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7404 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7406 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7407 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7408 if (!nspace_table) {
7409 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7410 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7411 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7414 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7418 g_hash_table_destroy (name_cache2);
7420 mono_image_lock (image);
7421 if (image->name_cache) {
7422 /* Somebody initialized it before us */
7423 g_hash_table_destroy (the_name_cache);
7425 mono_atomic_store_release (&image->name_cache, the_name_cache);
7427 mono_image_unlock (image);
7430 /*FIXME Only dynamic assemblies should allow this operation.*/
7432 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7433 const char *name, guint32 index)
7435 GHashTable *nspace_table;
7436 GHashTable *name_cache;
7439 mono_image_init_name_cache (image);
7440 mono_image_lock (image);
7442 name_cache = image->name_cache;
7443 if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7444 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7445 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7448 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7449 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7451 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7453 mono_image_unlock (image);
7462 find_nocase (gpointer key, gpointer value, gpointer user_data)
7464 char *name = (char*)key;
7465 FindUserData *data = (FindUserData*)user_data;
7467 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7468 data->value = value;
7472 * mono_class_from_name_case:
7473 * @image: The MonoImage where the type is looked up in
7474 * @name_space: the type namespace
7475 * @name: the type short name.
7476 * @deprecated: use the mono_class_from_name_case_checked variant instead.
7478 * Obtains a MonoClass with a given namespace and a given name which
7479 * is located in the given MonoImage. The namespace and name
7480 * lookups are case insensitive.
7483 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7486 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7487 mono_error_cleanup (&error);
7493 * mono_class_from_name_case:
7494 * @image: The MonoImage where the type is looked up in
7495 * @name_space: the type namespace
7496 * @name: the type short name.
7499 * Obtains a MonoClass with a given namespace and a given name which
7500 * is located in the given MonoImage. The namespace and name
7501 * lookups are case insensitive.
7503 * Returns: The MonoClass if the given namespace and name were found, or NULL if it
7504 * was not found. The @error object will contain information about the problem
7508 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7510 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7511 guint32 cols [MONO_TYPEDEF_SIZE];
7516 mono_error_init (error);
7518 if (image_is_dynamic (image)) {
7520 FindUserData user_data;
7522 mono_image_init_name_cache (image);
7523 mono_image_lock (image);
7525 user_data.key = name_space;
7526 user_data.value = NULL;
7527 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7529 if (user_data.value) {
7530 GHashTable *nspace_table = (GHashTable*)user_data.value;
7532 user_data.key = name;
7533 user_data.value = NULL;
7535 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7537 if (user_data.value)
7538 token = GPOINTER_TO_UINT (user_data.value);
7541 mono_image_unlock (image);
7544 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7550 /* add a cache if needed */
7551 for (i = 1; i <= t->rows; ++i) {
7552 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7553 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7555 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7556 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7558 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7560 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7561 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7562 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7563 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7569 return_nested_in (MonoClass *klass, char *nested)
7572 char *s = strchr (nested, '/');
7573 gpointer iter = NULL;
7580 while ((found = mono_class_get_nested_types (klass, &iter))) {
7581 if (strcmp (found->name, nested) == 0) {
7583 return return_nested_in (found, s);
7591 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7593 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7594 MonoImage *file_image;
7598 mono_error_init (error);
7601 * The EXPORTEDTYPES table only contains public types, so have to search the
7603 * Note: image->modules contains the contents of the MODULEREF table, while
7604 * the real module list is in the FILE table.
7606 for (i = 0; i < file_table->rows; i++) {
7607 guint32 cols [MONO_FILE_SIZE];
7608 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7609 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7612 file_image = mono_image_load_file_for_image_checked (image, i + 1, error);
7614 klass = mono_class_from_name_checked (file_image, name_space, name, error);
7615 if (klass || !is_ok (error))
7624 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7626 GHashTable *nspace_table;
7627 MonoImage *loaded_image;
7634 mono_error_init (error);
7636 // Checking visited images avoids stack overflows when cyclic references exist.
7637 if (g_hash_table_lookup (visited_images, image))
7640 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7642 if ((nested = strchr (name, '/'))) {
7643 int pos = nested - name;
7644 int len = strlen (name);
7647 memcpy (buf, name, len + 1);
7649 nested = buf + pos + 1;
7653 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7654 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7655 gboolean res = get_class_from_name (image, name_space, name, &klass);
7658 klass = search_modules (image, name_space, name, error);
7663 return klass ? return_nested_in (klass, nested) : NULL;
7669 mono_image_init_name_cache (image);
7670 mono_image_lock (image);
7672 nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7675 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7677 mono_image_unlock (image);
7679 if (!token && image_is_dynamic (image) && image->modules) {
7680 /* Search modules as well */
7681 for (i = 0; i < image->module_count; ++i) {
7682 MonoImage *module = image->modules [i];
7684 klass = mono_class_from_name_checked (module, name_space, name, error);
7685 if (klass || !is_ok (error))
7691 klass = search_modules (image, name_space, name, error);
7692 if (klass || !is_ok (error))
7697 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7698 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7699 guint32 cols [MONO_EXP_TYPE_SIZE];
7702 idx = mono_metadata_token_index (token);
7704 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7706 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7707 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7708 loaded_image = mono_assembly_load_module_checked (image->assembly, impl >> MONO_IMPLEMENTATION_BITS, error);
7711 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7713 return klass ? return_nested_in (klass, nested) : NULL;
7715 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7716 guint32 assembly_idx;
7718 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7720 mono_assembly_load_reference (image, assembly_idx - 1);
7721 g_assert (image->references [assembly_idx - 1]);
7722 if (image->references [assembly_idx - 1] == (gpointer)-1)
7724 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
7726 return klass ? return_nested_in (klass, nested) : NULL;
7729 g_assert_not_reached ();
7733 token = MONO_TOKEN_TYPE_DEF | token;
7735 klass = mono_class_get_checked (image, token, error);
7737 return return_nested_in (klass, nested);
7742 * mono_class_from_name_checked:
7743 * @image: The MonoImage where the type is looked up in
7744 * @name_space: the type namespace
7745 * @name: the type short name.
7747 * Obtains a MonoClass with a given namespace and a given name which
7748 * is located in the given MonoImage.
7750 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
7751 * set if the class was not found or it will return NULL and set the error if there was a loading error.
7754 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7757 GHashTable *visited_images;
7759 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7761 klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
7763 g_hash_table_destroy (visited_images);
7769 * mono_class_from_name:
7770 * @image: The MonoImage where the type is looked up in
7771 * @name_space: the type namespace
7772 * @name: the type short name.
7774 * Obtains a MonoClass with a given namespace and a given name which
7775 * is located in the given MonoImage.
7777 * To reference nested classes, use the "/" character as a separator.
7778 * For example use "Foo/Bar" to reference the class Bar that is nested
7779 * inside Foo, like this: "class Foo { class Bar {} }".
7782 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7787 klass = mono_class_from_name_checked (image, name_space, name, &error);
7788 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
7794 * mono_class_load_from_name:
7795 * @image: The MonoImage where the type is looked up in
7796 * @name_space: the type namespace
7797 * @name: the type short name.
7799 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
7800 * This function should be used by the runtime for critical types to which there's no way to recover but crash
7801 * If they are missing. Thing of System.Object or System.String.
7804 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
7809 klass = mono_class_from_name_checked (image, name_space, name, &error);
7811 g_error ("Runtime critical type %s.%s not found", name_space, name);
7812 if (!mono_error_ok (&error))
7813 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
7818 * mono_class_try_load_from_name:
7819 * @image: The MonoImage where the type is looked up in
7820 * @name_space: the type namespace
7821 * @name: the type short name.
7823 * This function tries to load a type, returning the class was found or NULL otherwise.
7824 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
7826 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
7827 * a type that we would otherwise assume to be available but was not due some error.
7831 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
7836 klass = mono_class_from_name_checked (image, name_space, name, &error);
7837 if (!mono_error_ok (&error))
7838 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
7844 * mono_class_is_subclass_of:
7845 * @klass: class to probe if it is a subclass of another one
7846 * @klassc: the class we suspect is the base class
7847 * @check_interfaces: whether we should perform interface checks
7849 * This method determines whether @klass is a subclass of @klassc.
7851 * If the @check_interfaces flag is set, then if @klassc is an interface
7852 * this method return TRUE if the @klass implements the interface or
7853 * if @klass is an interface, if one of its base classes is @klass.
7855 * If @check_interfaces is false then, then if @klass is not an interface
7856 * then it returns TRUE if the @klass is a subclass of @klassc.
7858 * if @klass is an interface and @klassc is System.Object, then this function
7863 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
7864 gboolean check_interfaces)
7866 /* FIXME test for interfaces with variant generic arguments */
7867 mono_class_init (klass);
7868 mono_class_init (klassc);
7870 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
7871 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
7873 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
7876 for (i = 0; i < klass->interface_count; i ++) {
7877 MonoClass *ic = klass->interfaces [i];
7882 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
7887 * MS.NET thinks interfaces are a subclass of Object, so we think it as
7890 if (klassc == mono_defaults.object_class)
7897 mono_type_is_generic_argument (MonoType *type)
7899 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
7903 mono_class_has_variant_generic_params (MonoClass *klass)
7906 MonoGenericContainer *container;
7908 if (!mono_class_is_ginst (klass))
7911 container = mono_class_get_generic_container (mono_class_get_generic_class (klass)->container_class);
7913 for (i = 0; i < container->type_argc; ++i)
7914 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
7921 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
7923 if (target == candidate)
7926 if (check_for_reference_conv &&
7927 mono_type_is_generic_argument (&target->byval_arg) &&
7928 mono_type_is_generic_argument (&candidate->byval_arg)) {
7929 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
7930 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
7932 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
7935 if (!mono_class_is_assignable_from (target, candidate))
7941 * @container the generic container from the GTD
7942 * @klass: the class to be assigned to
7943 * @oklass: the source class
7945 * Both @klass and @oklass must be instances of the same generic interface.
7947 * Returns: TRUE if @klass can be assigned to a @klass variable
7950 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
7953 MonoType **klass_argv, **oklass_argv;
7954 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7955 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
7957 if (klass == oklass)
7960 /*Viable candidates are instances of the same generic interface*/
7961 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7964 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
7965 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
7967 for (j = 0; j < container->type_argc; ++j) {
7968 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
7969 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
7971 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
7975 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
7976 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
7978 if (param1_class != param2_class) {
7979 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
7980 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
7982 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
7983 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
7993 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
7995 MonoGenericParam *gparam, *ogparam;
7996 MonoGenericParamInfo *tinfo, *cinfo;
7997 MonoClass **candidate_class;
7998 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8001 if (target == candidate)
8003 if (target->byval_arg.type != candidate->byval_arg.type)
8006 gparam = target->byval_arg.data.generic_param;
8007 ogparam = candidate->byval_arg.data.generic_param;
8008 tinfo = mono_generic_param_info (gparam);
8009 cinfo = mono_generic_param_info (ogparam);
8011 class_constraint_satisfied = FALSE;
8012 valuetype_constraint_satisfied = FALSE;
8014 /*candidate must have a super set of target's special constraints*/
8015 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8016 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8018 if (cinfo->constraints) {
8019 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8020 MonoClass *cc = *candidate_class;
8022 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8023 class_constraint_satisfied = TRUE;
8024 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8025 valuetype_constraint_satisfied = TRUE;
8028 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8029 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8031 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8033 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8035 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8036 valuetype_constraint_satisfied)) {
8041 /*candidate type constraints must be a superset of target's*/
8042 if (tinfo->constraints) {
8043 MonoClass **target_class;
8044 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8045 MonoClass *tc = *target_class;
8048 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8049 * check it's constraints since it satisfy the constraint by itself.
8051 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8054 if (!cinfo->constraints)
8057 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8058 MonoClass *cc = *candidate_class;
8060 if (mono_class_is_assignable_from (tc, cc))
8064 * This happens when we have the following:
8066 * Bar<K> where K : IFace
8067 * Foo<T, U> where T : U where U : IFace
8069 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8072 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8073 if (mono_gparam_is_assignable_from (target, cc))
8077 if (!*candidate_class)
8082 /*candidate itself must have a constraint that satisfy target*/
8083 if (cinfo->constraints) {
8084 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8085 MonoClass *cc = *candidate_class;
8086 if (mono_class_is_assignable_from (target, cc))
8094 * mono_class_is_assignable_from:
8095 * @klass: the class to be assigned to
8096 * @oklass: the source class
8098 * Returns: TRUE if an instance of object oklass can be assigned to an
8099 * instance of object @klass
8102 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8105 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8107 mono_class_init (klass);
8109 if (!oklass->inited)
8110 mono_class_init (oklass);
8112 if (mono_class_has_failure (klass) || mono_class_has_failure (oklass))
8115 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8116 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8118 return mono_gparam_is_assignable_from (klass, oklass);
8121 if (MONO_CLASS_IS_INTERFACE (klass)) {
8122 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8123 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8124 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8128 for (i = 0; constraints [i]; ++i) {
8129 if (mono_class_is_assignable_from (klass, constraints [i]))
8137 /* interface_offsets might not be set for dynamic classes */
8138 if (mono_class_get_ref_info_handle (oklass) && !oklass->interface_bitmap) {
8140 * oklass might be a generic type parameter but they have
8141 * interface_offsets set.
8143 gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8144 if (!is_ok (&error)) {
8145 mono_error_cleanup (&error);
8150 if (!oklass->interface_bitmap)
8151 /* Happens with generic instances of not-yet created dynamic types */
8153 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8156 if (klass->is_array_special_interface && oklass->rank == 1) {
8157 //XXX we could offset this by having the cast target computed at JIT time
8158 //XXX we could go even further and emit a wrapper that would do the extra type check
8159 MonoClass *iface_klass = mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
8160 MonoClass *obj_klass = oklass->cast_class; //This gets us the cast class of element type of the array
8162 // 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
8163 // We can't apply it for ref types as this would go wrong with arrays - IList<byte[]> would have byte tested
8164 if (iface_klass->valuetype)
8165 iface_klass = iface_klass->cast_class;
8167 //array covariant casts only operates on scalar to scalar
8168 //This is so int[] can't be casted to IComparable<int>[]
8169 if (!(obj_klass->valuetype && !iface_klass->valuetype) && mono_class_is_assignable_from (iface_klass, obj_klass))
8173 if (mono_class_has_variant_generic_params (klass)) {
8175 mono_class_setup_interfaces (oklass, &error);
8176 if (!mono_error_ok (&error)) {
8177 mono_error_cleanup (&error);
8181 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8182 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8183 MonoClass *iface = oklass->interfaces_packed [i];
8185 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8190 } else if (klass->delegate) {
8191 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8193 }else if (klass->rank) {
8194 MonoClass *eclass, *eoclass;
8196 if (oklass->rank != klass->rank)
8199 /* vectors vs. one dimensional arrays */
8200 if (oklass->byval_arg.type != klass->byval_arg.type)
8203 eclass = klass->cast_class;
8204 eoclass = oklass->cast_class;
8207 * a is b does not imply a[] is b[] when a is a valuetype, and
8208 * b is a reference type.
8211 if (eoclass->valuetype) {
8212 if ((eclass == mono_defaults.enum_class) ||
8213 (eclass == mono_defaults.enum_class->parent) ||
8214 (eclass == mono_defaults.object_class))
8218 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8219 } else if (mono_class_is_nullable (klass)) {
8220 if (mono_class_is_nullable (oklass))
8221 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8223 return mono_class_is_assignable_from (klass->cast_class, oklass);
8224 } else if (klass == mono_defaults.object_class)
8227 return mono_class_has_parent (oklass, klass);
8230 /*Check if @oklass is variant compatible with @klass.*/
8232 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8235 MonoType **klass_argv, **oklass_argv;
8236 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8237 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8239 /*Viable candidates are instances of the same generic interface*/
8240 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8243 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8244 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8246 for (j = 0; j < container->type_argc; ++j) {
8247 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8248 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8250 if (param1_class->valuetype != param2_class->valuetype)
8254 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8255 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8257 if (param1_class != param2_class) {
8258 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8259 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8261 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8262 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8270 /*Check if @candidate implements the interface @target*/
8272 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8276 gboolean is_variant = mono_class_has_variant_generic_params (target);
8278 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8279 if (mono_class_is_variant_compatible_slow (target, candidate))
8284 if (candidate == target)
8287 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8288 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8289 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info_raw (candidate); /* FIXME use handles */
8291 if (tb && tb->interfaces) {
8292 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8293 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8294 MonoClass *iface_class;
8296 /* we can't realize the type here since it can do pretty much anything. */
8299 iface_class = mono_class_from_mono_type (iface->type);
8300 if (iface_class == target)
8302 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8304 if (mono_class_implement_interface_slow (target, iface_class))
8309 /*setup_interfaces don't mono_class_init anything*/
8310 /*FIXME this doesn't handle primitive type arrays.
8311 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8312 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8314 mono_class_setup_interfaces (candidate, &error);
8315 if (!mono_error_ok (&error)) {
8316 mono_error_cleanup (&error);
8320 for (i = 0; i < candidate->interface_count; ++i) {
8321 if (candidate->interfaces [i] == target)
8324 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8327 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8331 candidate = candidate->parent;
8332 } while (candidate);
8338 * Check if @oklass can be assigned to @klass.
8339 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8342 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8344 if (candidate == target)
8346 if (target == mono_defaults.object_class)
8349 if (mono_class_has_parent (candidate, target))
8352 /*If target is not an interface there is no need to check them.*/
8353 if (MONO_CLASS_IS_INTERFACE (target))
8354 return mono_class_implement_interface_slow (target, candidate);
8356 if (target->delegate && mono_class_has_variant_generic_params (target))
8357 return mono_class_is_variant_compatible (target, candidate, FALSE);
8360 MonoClass *eclass, *eoclass;
8362 if (target->rank != candidate->rank)
8365 /* vectors vs. one dimensional arrays */
8366 if (target->byval_arg.type != candidate->byval_arg.type)
8369 eclass = target->cast_class;
8370 eoclass = candidate->cast_class;
8373 * a is b does not imply a[] is b[] when a is a valuetype, and
8374 * b is a reference type.
8377 if (eoclass->valuetype) {
8378 if ((eclass == mono_defaults.enum_class) ||
8379 (eclass == mono_defaults.enum_class->parent) ||
8380 (eclass == mono_defaults.object_class))
8384 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8386 /*FIXME properly handle nullables */
8387 /*FIXME properly handle (M)VAR */
8392 * mono_class_get_cctor:
8393 * @klass: A MonoClass pointer
8395 * Returns: The static constructor of @klass if it exists, NULL otherwise.
8398 mono_class_get_cctor (MonoClass *klass)
8400 MonoCachedClassInfo cached_info;
8402 if (image_is_dynamic (klass->image)) {
8404 * has_cctor is not set for these classes because mono_class_init () is
8407 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8410 mono_class_init (klass);
8412 if (!klass->has_cctor)
8415 if (mono_class_is_ginst (klass) && !klass->methods)
8416 return mono_class_get_inflated_method (klass, mono_class_get_cctor (mono_class_get_generic_class (klass)->container_class));
8418 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8420 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8421 if (!mono_error_ok (&error))
8422 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8426 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8430 * mono_class_get_finalizer:
8431 * @klass: The MonoClass pointer
8433 * Returns: The finalizer method of @klass if it exists, NULL otherwise.
8436 mono_class_get_finalizer (MonoClass *klass)
8438 MonoCachedClassInfo cached_info;
8441 mono_class_init (klass);
8442 if (!mono_class_has_finalizer (klass))
8445 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8447 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8448 if (!mono_error_ok (&error))
8449 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8452 mono_class_setup_vtable (klass);
8453 return klass->vtable [finalize_slot];
8458 * mono_class_needs_cctor_run:
8459 * @klass: the MonoClass pointer
8460 * @caller: a MonoMethod describing the caller
8462 * Determines whenever the class has a static constructor and whenever it
8463 * needs to be called when executing CALLER.
8466 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8470 method = mono_class_get_cctor (klass);
8472 return (method == caller) ? FALSE : TRUE;
8478 * mono_class_array_element_size:
8481 * Returns: The number of bytes an element of type @klass
8482 * uses when stored into an array.
8485 mono_class_array_element_size (MonoClass *klass)
8487 MonoType *type = &klass->byval_arg;
8490 switch (type->type) {
8493 case MONO_TYPE_BOOLEAN:
8497 case MONO_TYPE_CHAR:
8506 case MONO_TYPE_CLASS:
8507 case MONO_TYPE_STRING:
8508 case MONO_TYPE_OBJECT:
8509 case MONO_TYPE_SZARRAY:
8510 case MONO_TYPE_ARRAY:
8511 return sizeof (gpointer);
8516 case MONO_TYPE_VALUETYPE:
8517 if (type->data.klass->enumtype) {
8518 type = mono_class_enum_basetype (type->data.klass);
8519 klass = klass->element_class;
8522 return mono_class_instance_size (klass) - sizeof (MonoObject);
8523 case MONO_TYPE_GENERICINST:
8524 type = &type->data.generic_class->container_class->byval_arg;
8527 case MONO_TYPE_MVAR: {
8530 return mono_type_size (type, &align);
8532 case MONO_TYPE_VOID:
8536 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8542 * mono_array_element_size:
8543 * @ac: pointer to a #MonoArrayClass
8545 * Returns: The size of single array element.
8548 mono_array_element_size (MonoClass *ac)
8550 g_assert (ac->rank);
8551 return ac->sizes.element_size;
8555 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8556 MonoGenericContext *context)
8559 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8560 g_assert (mono_error_ok (&error));
8565 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8566 MonoGenericContext *context, MonoError *error)
8568 mono_error_init (error);
8570 if (image_is_dynamic (image)) {
8571 MonoClass *tmp_handle_class;
8572 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
8574 mono_error_assert_ok (error);
8575 g_assert (tmp_handle_class);
8577 *handle_class = tmp_handle_class;
8579 if (tmp_handle_class == mono_defaults.typehandle_class)
8580 return &((MonoClass*)obj)->byval_arg;
8585 switch (token & 0xff000000) {
8586 case MONO_TOKEN_TYPE_DEF:
8587 case MONO_TOKEN_TYPE_REF:
8588 case MONO_TOKEN_TYPE_SPEC: {
8591 *handle_class = mono_defaults.typehandle_class;
8592 type = mono_type_get_checked (image, token, context, error);
8596 mono_class_init (mono_class_from_mono_type (type));
8597 /* We return a MonoType* as handle */
8600 case MONO_TOKEN_FIELD_DEF: {
8602 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8604 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8608 *handle_class = mono_defaults.fieldhandle_class;
8609 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8613 mono_class_init (klass);
8614 return mono_class_get_field (klass, token);
8616 case MONO_TOKEN_METHOD_DEF:
8617 case MONO_TOKEN_METHOD_SPEC: {
8619 meth = mono_get_method_checked (image, token, NULL, context, error);
8621 *handle_class = mono_defaults.methodhandle_class;
8627 case MONO_TOKEN_MEMBER_REF: {
8628 guint32 cols [MONO_MEMBERREF_SIZE];
8630 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8631 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8632 mono_metadata_decode_blob_size (sig, &sig);
8633 if (*sig == 0x6) { /* it's a field */
8635 MonoClassField *field;
8636 field = mono_field_from_token_checked (image, token, &klass, context, error);
8638 *handle_class = mono_defaults.fieldhandle_class;
8642 meth = mono_get_method_checked (image, token, NULL, context, error);
8644 *handle_class = mono_defaults.methodhandle_class;
8649 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8655 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
8657 MonoClass *handle_class;
8658 mono_error_init (error);
8659 return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
8663 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
8665 return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
8668 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8671 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8673 get_cached_class_info = func;
8677 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8679 if (!get_cached_class_info)
8682 return get_cached_class_info (klass, res);
8686 mono_install_get_class_from_name (MonoGetClassFromName func)
8688 get_class_from_name = func;
8692 * mono_class_get_image:
8694 * Use this method to get the `MonoImage*` where this class came from.
8696 * Returns: The image where this class is defined.
8699 mono_class_get_image (MonoClass *klass)
8701 return klass->image;
8705 * mono_class_get_element_class:
8706 * @klass: the MonoClass to act on
8708 * Use this function to get the element class of an array.
8710 * Returns: The element class of an array.
8713 mono_class_get_element_class (MonoClass *klass)
8715 return klass->element_class;
8719 * mono_class_is_valuetype:
8720 * @klass: the MonoClass to act on
8722 * Use this method to determine if the provided `MonoClass*` represents a value type,
8723 * or a reference type.
8725 * Returns: TRUE if the MonoClass represents a ValueType, FALSE if it represents a reference type.
8728 mono_class_is_valuetype (MonoClass *klass)
8730 return klass->valuetype;
8734 * mono_class_is_enum:
8735 * @klass: the MonoClass to act on
8737 * Use this function to determine if the provided `MonoClass*` represents an enumeration.
8739 * Returns: TRUE if the MonoClass represents an enumeration.
8742 mono_class_is_enum (MonoClass *klass)
8744 return klass->enumtype;
8748 * mono_class_enum_basetype:
8749 * @klass: the MonoClass to act on
8751 * Use this function to get the underlying type for an enumeration value.
8753 * Returns: The underlying type representation for an enumeration.
8756 mono_class_enum_basetype (MonoClass *klass)
8758 if (klass->element_class == klass)
8759 /* SRE or broken types */
8762 return &klass->element_class->byval_arg;
8766 * mono_class_get_parent
8767 * @klass: the MonoClass to act on
8769 * Returns: The parent class for this class.
8772 mono_class_get_parent (MonoClass *klass)
8774 return klass->parent;
8778 * mono_class_get_nesting_type:
8779 * @klass: the MonoClass to act on
8781 * Use this function to obtain the class that the provided `MonoClass*` is nested on.
8783 * If the return is NULL, this indicates that this class is not nested.
8785 * Returns: The container type where this type is nested or NULL if this type is not a nested type.
8788 mono_class_get_nesting_type (MonoClass *klass)
8790 return klass->nested_in;
8794 * mono_class_get_rank:
8795 * @klass: the MonoClass to act on
8797 * Returns: The rank for the array (the number of dimensions).
8800 mono_class_get_rank (MonoClass *klass)
8806 * mono_class_get_name
8807 * @klass: the MonoClass to act on
8809 * Returns: The name of the class.
8812 mono_class_get_name (MonoClass *klass)
8818 * mono_class_get_namespace:
8819 * @klass: the MonoClass to act on
8821 * Returns: The namespace of the class.
8824 mono_class_get_namespace (MonoClass *klass)
8826 return klass->name_space;
8830 * mono_class_get_type:
8831 * @klass: the MonoClass to act on
8833 * This method returns the internal Type representation for the class.
8835 * Returns: The MonoType from the class.
8838 mono_class_get_type (MonoClass *klass)
8840 return &klass->byval_arg;
8844 * mono_class_get_type_token:
8845 * @klass: the MonoClass to act on
8847 * This method returns type token for the class.
8849 * Returns: The type token for the class.
8852 mono_class_get_type_token (MonoClass *klass)
8854 return klass->type_token;
8858 * mono_class_get_byref_type:
8859 * @klass: the MonoClass to act on
8864 mono_class_get_byref_type (MonoClass *klass)
8866 return &klass->this_arg;
8870 * mono_class_num_fields:
8871 * @klass: the MonoClass to act on
8873 * Returns: The number of static and instance fields in the class.
8876 mono_class_num_fields (MonoClass *klass)
8878 return mono_class_get_field_count (klass);
8882 * mono_class_num_methods:
8883 * @klass: the MonoClass to act on
8885 * Returns: The number of methods in the class.
8888 mono_class_num_methods (MonoClass *klass)
8890 return mono_class_get_method_count (klass);
8894 * mono_class_num_properties
8895 * @klass: the MonoClass to act on
8897 * Returns: The number of properties in the class.
8900 mono_class_num_properties (MonoClass *klass)
8902 mono_class_setup_properties (klass);
8904 return mono_class_get_property_info (klass)->count;
8908 * mono_class_num_events:
8909 * @klass: the MonoClass to act on
8911 * Returns: The number of events in the class.
8914 mono_class_num_events (MonoClass *klass)
8916 mono_class_setup_events (klass);
8918 return mono_class_get_event_info (klass)->count;
8922 * mono_class_get_fields:
8923 * @klass: the MonoClass to act on
8925 * This routine is an iterator routine for retrieving the fields in a class.
8927 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8928 * iterate over all of the elements. When no more values are
8929 * available, the return value is NULL.
8931 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
8934 mono_class_get_fields (MonoClass* klass, gpointer *iter)
8936 MonoClassField* field;
8940 mono_class_setup_fields (klass);
8941 if (mono_class_has_failure (klass))
8943 /* start from the first */
8944 if (mono_class_get_field_count (klass)) {
8945 *iter = &klass->fields [0];
8946 return &klass->fields [0];
8952 field = (MonoClassField *)*iter;
8954 if (field < &klass->fields [mono_class_get_field_count (klass)]) {
8962 * mono_class_get_methods
8963 * @klass: the MonoClass to act on
8965 * This routine is an iterator routine for retrieving the fields in a class.
8967 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8968 * iterate over all of the elements. When no more values are
8969 * available, the return value is NULL.
8971 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
8974 mono_class_get_methods (MonoClass* klass, gpointer *iter)
8976 MonoMethod** method;
8980 mono_class_setup_methods (klass);
8983 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8984 * FIXME we should better report this error to the caller
8986 if (!klass->methods)
8988 /* start from the first */
8989 if (mono_class_get_method_count (klass)) {
8990 *iter = &klass->methods [0];
8991 return klass->methods [0];
8997 method = (MonoMethod **)*iter;
8999 if (method < &klass->methods [mono_class_get_method_count (klass)]) {
9007 * mono_class_get_virtual_methods:
9009 * Iterate over the virtual methods of KLASS.
9011 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9014 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9016 MonoMethod** method;
9019 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9021 mono_class_setup_methods (klass);
9023 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9024 * FIXME we should better report this error to the caller
9026 if (!klass->methods)
9028 /* start from the first */
9029 method = &klass->methods [0];
9031 method = (MonoMethod **)*iter;
9034 int mcount = mono_class_get_method_count (klass);
9035 while (method < &klass->methods [mcount]) {
9036 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9040 if (method < &klass->methods [mcount]) {
9047 /* Search directly in metadata to avoid calling setup_methods () */
9048 MonoMethod *res = NULL;
9054 start_index = GPOINTER_TO_UINT (*iter);
9057 int first_idx = mono_class_get_first_method_idx (klass);
9058 int mcount = mono_class_get_method_count (klass);
9059 for (i = start_index; i < mcount; ++i) {
9062 /* first_idx points into the methodptr table */
9063 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
9065 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9071 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9072 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9074 /* Add 1 here so the if (*iter) check fails */
9075 *iter = GUINT_TO_POINTER (i + 1);
9084 * mono_class_get_properties:
9085 * @klass: the MonoClass to act on
9087 * This routine is an iterator routine for retrieving the properties in a class.
9089 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9090 * iterate over all of the elements. When no more values are
9091 * available, the return value is NULL.
9093 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9096 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9098 MonoProperty* property;
9102 mono_class_setup_properties (klass);
9103 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
9104 /* start from the first */
9106 *iter = &info->properties [0];
9107 return (MonoProperty *)*iter;
9113 property = (MonoProperty *)*iter;
9115 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
9116 if (property < &info->properties [info->count]) {
9118 return (MonoProperty *)*iter;
9124 * mono_class_get_events:
9125 * @klass: the MonoClass to act on
9127 * This routine is an iterator routine for retrieving the properties in a class.
9129 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9130 * iterate over all of the elements. When no more values are
9131 * available, the return value is NULL.
9133 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9136 mono_class_get_events (MonoClass* klass, gpointer *iter)
9142 mono_class_setup_events (klass);
9143 MonoClassEventInfo *info = mono_class_get_event_info (klass);
9144 /* start from the first */
9146 *iter = &info->events [0];
9147 return (MonoEvent *)*iter;
9153 event = (MonoEvent *)*iter;
9155 MonoClassEventInfo *info = mono_class_get_event_info (klass);
9156 if (event < &info->events [info->count]) {
9158 return (MonoEvent *)*iter;
9164 * mono_class_get_interfaces
9165 * @klass: the MonoClass to act on
9167 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9169 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9170 * iterate over all of the elements. When no more values are
9171 * available, the return value is NULL.
9173 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9176 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9184 mono_class_init (klass);
9185 if (!klass->interfaces_inited) {
9186 mono_class_setup_interfaces (klass, &error);
9187 if (!mono_error_ok (&error)) {
9188 mono_error_cleanup (&error);
9192 /* start from the first */
9193 if (klass->interface_count) {
9194 *iter = &klass->interfaces [0];
9195 return klass->interfaces [0];
9201 iface = (MonoClass **)*iter;
9203 if (iface < &klass->interfaces [klass->interface_count]) {
9211 setup_nested_types (MonoClass *klass)
9214 GList *classes, *nested_classes, *l;
9217 if (klass->nested_classes_inited)
9220 if (!klass->type_token) {
9221 mono_loader_lock ();
9222 klass->nested_classes_inited = TRUE;
9223 mono_loader_unlock ();
9227 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9231 guint32 cols [MONO_NESTED_CLASS_SIZE];
9232 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9233 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9234 if (!mono_error_ok (&error)) {
9235 /*FIXME don't swallow the error message*/
9236 mono_error_cleanup (&error);
9238 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9242 classes = g_list_prepend (classes, nclass);
9244 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9247 nested_classes = NULL;
9248 for (l = classes; l; l = l->next)
9249 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9250 g_list_free (classes);
9252 mono_loader_lock ();
9253 if (!klass->nested_classes_inited) {
9254 mono_class_set_nested_classes_property (klass, nested_classes);
9255 mono_memory_barrier ();
9256 klass->nested_classes_inited = TRUE;
9258 mono_loader_unlock ();
9262 * mono_class_get_nested_types
9263 * @klass: the MonoClass to act on
9265 * This routine is an iterator routine for retrieving the nested types of a class.
9266 * This works only if @klass is non-generic, or a generic type definition.
9268 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9269 * iterate over all of the elements. When no more values are
9270 * available, the return value is NULL.
9272 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9275 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9281 if (!klass->nested_classes_inited)
9282 setup_nested_types (klass);
9285 GList *nested_classes = mono_class_get_nested_classes_property (klass);
9286 /* start from the first */
9287 if (nested_classes) {
9288 *iter = nested_classes;
9289 return (MonoClass *)nested_classes->data;
9291 /* no nested types */
9295 item = (GList *)*iter;
9299 return (MonoClass *)item->data;
9306 * mono_class_is_delegate
9307 * @klass: the MonoClass to act on
9309 * Returns: TRUE if the MonoClass represents a System.Delegate.
9312 mono_class_is_delegate (MonoClass *klass)
9314 return klass->delegate;
9318 * mono_class_implements_interface
9319 * @klass: The MonoClass to act on
9320 * @interface: The interface to check if @klass implements.
9322 * Returns: TRUE if @klass implements @interface.
9325 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9327 return mono_class_is_assignable_from (iface, klass);
9331 * mono_field_get_name:
9332 * @field: the MonoClassField to act on
9334 * Returns: The name of the field.
9337 mono_field_get_name (MonoClassField *field)
9343 * mono_field_get_type:
9344 * @field: the MonoClassField to act on
9346 * Returns: MonoType of the field.
9349 mono_field_get_type (MonoClassField *field)
9352 MonoType *type = mono_field_get_type_checked (field, &error);
9353 if (!mono_error_ok (&error)) {
9354 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9355 mono_error_cleanup (&error);
9362 * mono_field_get_type_checked:
9363 * @field: the MonoClassField to act on
9364 * @error: used to return any erro found while retrieving @field type
9366 * Returns: MonoType of the field.
9369 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9371 mono_error_init (error);
9373 mono_field_resolve_type (field, error);
9378 * mono_field_get_parent:
9379 * @field: the MonoClassField to act on
9381 * Returns: MonoClass where the field was defined.
9384 mono_field_get_parent (MonoClassField *field)
9386 return field->parent;
9390 * mono_field_get_flags;
9391 * @field: the MonoClassField to act on
9393 * The metadata flags for a field are encoded using the
9394 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9396 * Returns: The flags for the field.
9399 mono_field_get_flags (MonoClassField *field)
9402 return mono_field_resolve_flags (field);
9403 return field->type->attrs;
9407 * mono_field_get_offset:
9408 * @field: the MonoClassField to act on
9410 * Returns: The field offset.
9413 mono_field_get_offset (MonoClassField *field)
9415 return field->offset;
9419 mono_field_get_rva (MonoClassField *field)
9423 MonoClass *klass = field->parent;
9424 MonoFieldDefaultValue *def_values;
9426 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9428 def_values = mono_class_get_field_def_values (klass);
9430 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
9432 mono_class_set_field_def_values (klass, def_values);
9435 field_index = mono_field_get_index (field);
9437 if (!def_values [field_index].data && !image_is_dynamic (klass->image)) {
9438 int first_field_idx = mono_class_get_first_field_idx (klass);
9439 mono_metadata_field_info (field->parent->image, first_field_idx + field_index, NULL, &rva, NULL);
9441 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9442 def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9445 return def_values [field_index].data;
9449 * mono_field_get_data:
9450 * @field: the MonoClassField to act on
9452 * Returns: A pointer to the metadata constant value or to the field
9453 * data if it has an RVA flag.
9456 mono_field_get_data (MonoClassField *field)
9458 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9459 MonoTypeEnum def_type;
9461 return mono_class_get_field_default_value (field, &def_type);
9462 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9463 return mono_field_get_rva (field);
9470 * mono_property_get_name:
9471 * @prop: the MonoProperty to act on
9473 * Returns: The name of the property
9476 mono_property_get_name (MonoProperty *prop)
9482 * mono_property_get_set_method
9483 * @prop: the MonoProperty to act on.
9485 * Returns: The setter method of the property (A MonoMethod)
9488 mono_property_get_set_method (MonoProperty *prop)
9494 * mono_property_get_get_method
9495 * @prop: the MonoProperty to act on.
9497 * Returns: The setter method of the property (A MonoMethod)
9500 mono_property_get_get_method (MonoProperty *prop)
9506 * mono_property_get_parent:
9507 * @prop: the MonoProperty to act on.
9509 * Returns: The MonoClass where the property was defined.
9512 mono_property_get_parent (MonoProperty *prop)
9514 return prop->parent;
9518 * mono_property_get_flags:
9519 * @prop: the MonoProperty to act on.
9521 * The metadata flags for a property are encoded using the
9522 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9524 * Returns: The flags for the property.
9527 mono_property_get_flags (MonoProperty *prop)
9533 * mono_event_get_name:
9534 * @event: the MonoEvent to act on
9536 * Returns: The name of the event.
9539 mono_event_get_name (MonoEvent *event)
9545 * mono_event_get_add_method:
9546 * @event: The MonoEvent to act on.
9548 * Returns: The @add' method for the event (a MonoMethod).
9551 mono_event_get_add_method (MonoEvent *event)
9557 * mono_event_get_remove_method:
9558 * @event: The MonoEvent to act on.
9560 * Returns: The @remove method for the event (a MonoMethod).
9563 mono_event_get_remove_method (MonoEvent *event)
9565 return event->remove;
9569 * mono_event_get_raise_method:
9570 * @event: The MonoEvent to act on.
9572 * Returns: The @raise method for the event (a MonoMethod).
9575 mono_event_get_raise_method (MonoEvent *event)
9577 return event->raise;
9581 * mono_event_get_parent:
9582 * @event: the MonoEvent to act on.
9584 * Returns: The MonoClass where the event is defined.
9587 mono_event_get_parent (MonoEvent *event)
9589 return event->parent;
9593 * mono_event_get_flags
9594 * @event: the MonoEvent to act on.
9596 * The metadata flags for an event are encoded using the
9597 * EVENT_* constants. See the tabledefs.h file for details.
9599 * Returns: The flags for the event.
9602 mono_event_get_flags (MonoEvent *event)
9604 return event->attrs;
9608 * mono_class_get_method_from_name:
9609 * @klass: where to look for the method
9610 * @name: name of the method
9611 * @param_count: number of parameters. -1 for any number.
9613 * Obtains a MonoMethod with a given name and number of parameters.
9614 * It only works if there are no multiple signatures for any given method name.
9617 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9619 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9623 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9625 MonoMethod *res = NULL;
9628 /* Search directly in the metadata to avoid calling setup_methods () */
9629 int first_idx = mono_class_get_first_method_idx (klass);
9630 int mcount = mono_class_get_method_count (klass);
9631 for (i = 0; i < mcount; ++i) {
9633 guint32 cols [MONO_METHOD_SIZE];
9635 MonoMethodSignature *sig;
9637 /* first_idx points into the methodptr table */
9638 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, first_idx + i, cols, MONO_METHOD_SIZE);
9640 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9641 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9643 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9646 if (param_count == -1) {
9650 sig = mono_method_signature_checked (method, &error);
9652 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9655 if (sig->param_count == param_count) {
9666 * mono_class_get_method_from_name_flags:
9667 * @klass: where to look for the method
9668 * @name_space: name of the method
9669 * @param_count: number of parameters. -1 for any number.
9670 * @flags: flags which must be set in the method
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_flags (MonoClass *klass, const char *name, int param_count, int flags)
9678 MonoMethod *res = NULL;
9681 mono_class_init (klass);
9683 if (mono_class_is_ginst (klass) && !klass->methods) {
9684 res = mono_class_get_method_from_name_flags (mono_class_get_generic_class (klass)->container_class, name, param_count, flags);
9687 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9688 if (!mono_error_ok (&error))
9689 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9694 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9695 mono_class_setup_methods (klass);
9697 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9698 See mono/tests/array_load_exception.il
9699 FIXME we should better report this error to the caller
9701 if (!klass->methods)
9703 int mcount = mono_class_get_method_count (klass);
9704 for (i = 0; i < mcount; ++i) {
9705 MonoMethod *method = klass->methods [i];
9707 if (method->name[0] == name [0] &&
9708 !strcmp (name, method->name) &&
9709 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9710 ((method->flags & flags) == flags)) {
9717 res = find_method_in_metadata (klass, name, param_count, flags);
9724 * mono_class_set_failure:
9725 * @klass: class in which the failure was detected
9726 * @ex_type: the kind of exception/error to be thrown (later)
9727 * @ex_data: exception data (specific to each type of exception/error)
9729 * Keep a detected failure informations in the class for later processing.
9730 * Note that only the first failure is kept.
9732 * LOCKING: Acquires the loader lock.
9735 mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error)
9737 g_assert (boxed_error != NULL);
9739 if (mono_class_has_failure (klass))
9742 mono_loader_lock ();
9743 klass->has_failure = 1;
9744 mono_class_set_exception_data (klass, boxed_error);
9745 mono_loader_unlock ();
9751 mono_class_has_failure (const MonoClass *klass)
9753 g_assert (klass != NULL);
9754 return klass->has_failure != 0;
9759 * mono_class_set_type_load_failure:
9760 * @klass: class in which the failure was detected
9761 * @fmt: Printf-style error message string.
9763 * Collect detected failure informaion in the class for later processing.
9764 * The error is stored as a MonoErrorBoxed as with mono_error_set_type_load_class ()
9765 * Note that only the first failure is kept.
9767 * Returns FALSE if a failure was already set on the class, or TRUE otherwise.
9769 * LOCKING: Acquires the loader lock.
9772 mono_class_set_type_load_failure (MonoClass *klass, const char * fmt, ...)
9774 MonoError prepare_error;
9777 if (mono_class_has_failure (klass))
9780 mono_error_init (&prepare_error);
9782 va_start (args, fmt);
9783 mono_error_vset_type_load_class (&prepare_error, klass, fmt, args);
9786 MonoErrorBoxed *box = mono_error_box (&prepare_error, klass->image);
9787 mono_error_cleanup (&prepare_error);
9788 return mono_class_set_failure (klass, box);
9792 * mono_classes_init:
9794 * Initialize the resources used by this module.
9797 mono_classes_init (void)
9799 mono_os_mutex_init (&classes_mutex);
9801 mono_native_tls_alloc (&setup_fields_tls_id, NULL);
9802 mono_native_tls_alloc (&init_pending_tls_id, NULL);
9804 mono_counters_register ("MonoClassDef count",
9805 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_def_count);
9806 mono_counters_register ("MonoClassGtd count",
9807 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gtd_count);
9808 mono_counters_register ("MonoClassGenericInst count",
9809 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ginst_count);
9810 mono_counters_register ("MonoClassGenericParam count",
9811 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gparam_count);
9812 mono_counters_register ("MonoClassArray count",
9813 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_array_count);
9814 mono_counters_register ("MonoClassPointer count",
9815 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_pointer_count);
9816 mono_counters_register ("Inflated methods size",
9817 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9818 mono_counters_register ("Inflated classes size",
9819 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9820 mono_counters_register ("MonoClass size",
9821 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9825 * mono_classes_cleanup:
9827 * Free the resources used by this module.
9830 mono_classes_cleanup (void)
9832 mono_native_tls_free (setup_fields_tls_id);
9833 mono_native_tls_free (init_pending_tls_id);
9835 if (global_interface_bitset)
9836 mono_bitset_free (global_interface_bitset);
9837 global_interface_bitset = NULL;
9838 mono_os_mutex_destroy (&classes_mutex);
9842 * mono_class_get_exception_for_failure:
9843 * @klass: class in which the failure was detected
9845 * Return a constructed MonoException than the caller can then throw
9846 * using mono_raise_exception - or NULL if no failure is present (or
9847 * doesn't result in an exception).
9850 mono_class_get_exception_for_failure (MonoClass *klass)
9852 if (!mono_class_has_failure (klass))
9854 MonoError unboxed_error;
9855 mono_error_init (&unboxed_error);
9856 mono_error_set_for_class_failure (&unboxed_error, klass);
9857 return mono_error_convert_to_exception (&unboxed_error);
9861 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
9863 outer_klass = mono_class_get_generic_type_definition (outer_klass);
9864 inner_klass = mono_class_get_generic_type_definition (inner_klass);
9866 if (outer_klass == inner_klass)
9868 inner_klass = inner_klass->nested_in;
9869 } while (inner_klass);
9874 mono_class_get_generic_type_definition (MonoClass *klass)
9876 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
9877 return gklass ? gklass->container_class : klass;
9881 * Check if @klass is a subtype of @parent ignoring generic instantiations.
9883 * Generic instantiations are ignored for all super types of @klass.
9885 * Visibility checks ignoring generic instantiations.
9888 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
9891 klass = mono_class_get_generic_type_definition (klass);
9892 parent = mono_class_get_generic_type_definition (parent);
9893 mono_class_setup_supertypes (klass);
9895 for (i = 0; i < klass->idepth; ++i) {
9896 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
9902 * Subtype can only access parent members with family protection if the site object
9903 * is subclass of Subtype. For example:
9904 * class A { protected int x; }
9906 * void valid_access () {
9910 * void invalid_access () {
9917 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
9919 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
9922 if (context_klass == NULL)
9924 /*if access_klass is not member_klass context_klass must be type compat*/
9925 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
9931 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
9934 if (accessing == accessed)
9936 if (!accessed || !accessing)
9939 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
9940 * anywhere so untrusted friends are not safe to access platform's code internals */
9941 if (mono_security_core_clr_enabled ()) {
9942 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
9946 mono_assembly_load_friends (accessed);
9947 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
9948 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
9949 /* Be conservative with checks */
9952 if (strcmp (accessing->aname.name, friend_->name))
9954 if (friend_->public_key_token [0]) {
9955 if (!accessing->aname.public_key_token [0])
9957 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
9966 * If klass is a generic type or if it is derived from a generic type, return the
9967 * MonoClass of the generic definition
9968 * Returns NULL if not found
9971 get_generic_definition_class (MonoClass *klass)
9974 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
9975 if (gklass && gklass->container_class)
9976 return gklass->container_class;
9977 klass = klass->parent;
9983 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
9986 for (i = 0; i < ginst->type_argc; ++i) {
9987 MonoType *type = ginst->type_argv[i];
9988 switch (type->type) {
9989 case MONO_TYPE_SZARRAY:
9990 if (!can_access_type (access_klass, type->data.klass))
9993 case MONO_TYPE_ARRAY:
9994 if (!can_access_type (access_klass, type->data.array->eklass))
9998 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10001 case MONO_TYPE_CLASS:
10002 case MONO_TYPE_VALUETYPE:
10003 case MONO_TYPE_GENERICINST:
10004 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10014 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10018 if (access_klass == member_klass)
10021 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10024 if (access_klass->element_class && !access_klass->enumtype)
10025 access_klass = access_klass->element_class;
10027 if (member_klass->element_class && !member_klass->enumtype)
10028 member_klass = member_klass->element_class;
10030 access_level = mono_class_get_flags (member_klass) & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10032 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10035 if (mono_class_is_ginst (member_klass) && !can_access_instantiation (access_klass, mono_class_get_generic_class (member_klass)->context.class_inst))
10038 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10041 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10044 /*Non nested type with nested visibility. We just fail it.*/
10045 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10048 switch (access_level) {
10049 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10050 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10052 case TYPE_ATTRIBUTE_PUBLIC:
10055 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10058 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10059 return is_nesting_type (member_klass, access_klass);
10061 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10062 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10064 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10065 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10067 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10068 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10069 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10071 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10072 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10073 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10078 /* FIXME: check visibility of type, too */
10080 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10082 MonoClass *member_generic_def;
10083 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10086 MonoGenericClass *access_gklass = mono_class_try_get_generic_class (access_klass);
10087 if (((access_gklass && access_gklass->container_class) ||
10088 mono_class_is_gtd (access_klass)) &&
10089 (member_generic_def = get_generic_definition_class (member_klass))) {
10090 MonoClass *access_container;
10092 if (mono_class_is_gtd (access_klass))
10093 access_container = access_klass;
10095 access_container = access_gklass->container_class;
10097 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10101 /* Partition I 8.5.3.2 */
10102 /* the access level values are the same for fields and methods */
10103 switch (access_level) {
10104 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10105 /* same compilation unit */
10106 return access_klass->image == member_klass->image;
10107 case FIELD_ATTRIBUTE_PRIVATE:
10108 return access_klass == member_klass;
10109 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10110 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10111 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10114 case FIELD_ATTRIBUTE_ASSEMBLY:
10115 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10116 case FIELD_ATTRIBUTE_FAMILY:
10117 if (is_valid_family_access (access_klass, member_klass, context_klass))
10120 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10121 if (is_valid_family_access (access_klass, member_klass, context_klass))
10123 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10124 case FIELD_ATTRIBUTE_PUBLIC:
10131 * mono_method_can_access_field:
10132 * @method: Method that will attempt to access the field
10133 * @field: the field to access
10135 * Used to determine if a method is allowed to access the specified field.
10137 * Returns: TRUE if the given @method is allowed to access the @field while following
10138 * the accessibility rules of the CLI.
10141 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10143 /* FIXME: check all overlapping fields */
10144 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10146 MonoClass *nested = method->klass->nested_in;
10148 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10151 nested = nested->nested_in;
10158 * mono_method_can_access_method:
10159 * @method: Method that will attempt to access the other method
10160 * @called: the method that we want to probe for accessibility.
10162 * Used to determine if the @method is allowed to access the specified @called method.
10164 * Returns: TRUE if the given @method is allowed to invoke the @called while following
10165 * the accessibility rules of the CLI.
10168 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10170 method = mono_method_get_method_definition (method);
10171 called = mono_method_get_method_definition (called);
10172 return mono_method_can_access_method_full (method, called, NULL);
10176 * mono_method_can_access_method_full:
10177 * @method: The caller method
10178 * @called: The called method
10179 * @context_klass: The static type on stack of the owner @called object used
10181 * This function must be used with instance calls, as they have more strict family accessibility.
10182 * It can be used with static methods, but context_klass should be NULL.
10184 * Returns: TRUE if caller have proper visibility and acessibility to @called
10187 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10189 /* Wrappers are except from access checks */
10190 if (method->wrapper_type != MONO_WRAPPER_NONE || called->wrapper_type != MONO_WRAPPER_NONE)
10193 MonoClass *access_class = method->klass;
10194 MonoClass *member_class = called->klass;
10195 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10197 MonoClass *nested = access_class->nested_in;
10199 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10202 nested = nested->nested_in;
10209 can = can_access_type (access_class, member_class);
10211 MonoClass *nested = access_class->nested_in;
10213 can = can_access_type (nested, member_class);
10216 nested = nested->nested_in;
10223 if (called->is_inflated) {
10224 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10225 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10234 * mono_method_can_access_field_full:
10235 * @method: The caller method
10236 * @field: The accessed field
10237 * @context_klass: The static type on stack of the owner @field object used
10239 * This function must be used with instance fields, as they have more strict family accessibility.
10240 * It can be used with static fields, but context_klass should be NULL.
10242 * Returns: TRUE if caller have proper visibility and acessibility to @field
10245 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10247 MonoClass *access_class = method->klass;
10248 MonoClass *member_class = field->parent;
10249 /* FIXME: check all overlapping fields */
10250 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10252 MonoClass *nested = access_class->nested_in;
10254 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10257 nested = nested->nested_in;
10264 can = can_access_type (access_class, member_class);
10266 MonoClass *nested = access_class->nested_in;
10268 can = can_access_type (nested, member_class);
10271 nested = nested->nested_in;
10281 * mono_class_can_access_class:
10282 * @source_class: The source class
10283 * @target_class: The accessed class
10285 * This function returns is @target_class is visible to @source_class
10287 * Returns: TRUE if source have proper visibility and acessibility to target
10290 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10292 return can_access_type (source_class, target_class);
10296 * mono_type_is_valid_enum_basetype:
10297 * @type: The MonoType to check
10299 * Returns: TRUE if the type can be used as the basetype of an enum
10301 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10302 switch (type->type) {
10305 case MONO_TYPE_BOOLEAN:
10308 case MONO_TYPE_CHAR:
10322 * mono_class_is_valid_enum:
10323 * @klass: An enum class to be validated
10325 * This method verify the required properties an enum should have.
10327 * Returns: TRUE if the informed enum class is valid
10329 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10330 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10331 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10334 mono_class_is_valid_enum (MonoClass *klass)
10336 MonoClassField * field;
10337 gpointer iter = NULL;
10338 gboolean found_base_field = FALSE;
10340 g_assert (klass->enumtype);
10341 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10342 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10346 if (!mono_class_is_auto_layout (klass))
10349 while ((field = mono_class_get_fields (klass, &iter))) {
10350 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10351 if (found_base_field)
10353 found_base_field = TRUE;
10354 if (!mono_type_is_valid_enum_basetype (field->type))
10359 if (!found_base_field)
10362 if (mono_class_get_method_count (klass) > 0)
10369 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10371 return gklass->context.class_inst == mono_class_get_generic_container (gklass->container_class)->context.class_inst;
10375 * mono_class_setup_interface_id:
10377 * Initializes MonoClass::interface_id if required.
10379 * LOCKING: Acquires the loader lock.
10382 mono_class_setup_interface_id (MonoClass *klass)
10384 mono_loader_lock ();
10385 if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10386 klass->interface_id = mono_get_unique_iid (klass);
10387 mono_loader_unlock ();
10391 * mono_class_setup_interfaces:
10393 * Initialize klass->interfaces/interfaces_count.
10394 * LOCKING: Acquires the loader lock.
10395 * This function can fail the type.
10398 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10400 int i, interface_count;
10401 MonoClass **interfaces;
10403 mono_error_init (error);
10405 if (klass->interfaces_inited)
10408 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10409 MonoType *args [1];
10411 /* generic IList, ICollection, IEnumerable */
10412 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10413 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10415 args [0] = &klass->element_class->byval_arg;
10416 interfaces [0] = mono_class_bind_generic_parameters (
10417 mono_defaults.generic_ilist_class, 1, args, FALSE);
10418 if (interface_count > 1)
10419 interfaces [1] = mono_class_bind_generic_parameters (
10420 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10421 } else if (mono_class_is_ginst (klass)) {
10422 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
10424 mono_class_setup_interfaces (gklass, error);
10425 if (!mono_error_ok (error)) {
10426 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10430 interface_count = gklass->interface_count;
10431 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10432 for (i = 0; i < interface_count; i++) {
10433 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (mono_class_get_generic_class (klass)), error);
10434 if (!mono_error_ok (error)) {
10435 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10440 interface_count = 0;
10444 mono_loader_lock ();
10445 if (!klass->interfaces_inited) {
10446 klass->interface_count = interface_count;
10447 klass->interfaces = interfaces;
10449 mono_memory_barrier ();
10451 klass->interfaces_inited = TRUE;
10453 mono_loader_unlock ();
10457 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10459 MonoClass *klass = field->parent;
10460 MonoImage *image = klass->image;
10461 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10463 int field_idx = field - klass->fields;
10465 mono_error_init (error);
10468 MonoClassField *gfield = >d->fields [field_idx];
10469 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10470 if (!mono_error_ok (error)) {
10471 char *full_name = mono_type_get_full_name (gtd);
10472 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));
10473 g_free (full_name);
10476 ftype = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10477 if (!mono_error_ok (error)) {
10478 char *full_name = mono_type_get_full_name (klass);
10479 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));
10480 g_free (full_name);
10484 guint32 cols [MONO_FIELD_SIZE];
10485 MonoGenericContainer *container = NULL;
10486 int idx = mono_class_get_first_field_idx (klass) + field_idx;
10488 /*FIXME, in theory we do not lazy load SRE fields*/
10489 g_assert (!image_is_dynamic (image));
10491 if (mono_class_is_gtd (klass)) {
10492 container = mono_class_get_generic_container (klass);
10494 container = mono_class_get_generic_container (gtd);
10495 g_assert (container);
10498 /* first_field_idx and idx points into the fieldptr table */
10499 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10501 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10502 char *full_name = mono_type_get_full_name (klass);
10503 mono_error_set_type_load_class (error, klass, "Could not verify field '%s:%s' signature", full_name, field->name);;
10504 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
10505 g_free (full_name);
10509 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10511 mono_metadata_decode_value (sig, &sig);
10512 /* FIELD signature == 0x06 */
10513 g_assert (*sig == 0x06);
10515 ftype = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10517 char *full_name = mono_type_get_full_name (klass);
10518 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));
10519 g_free (full_name);
10522 mono_memory_barrier ();
10523 field->type = ftype;
10527 mono_field_resolve_flags (MonoClassField *field)
10529 MonoClass *klass = field->parent;
10530 MonoImage *image = klass->image;
10531 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10532 int field_idx = field - klass->fields;
10535 MonoClassField *gfield = >d->fields [field_idx];
10536 return mono_field_get_flags (gfield);
10538 int idx = mono_class_get_first_field_idx (klass) + field_idx;
10540 /*FIXME, in theory we do not lazy load SRE fields*/
10541 g_assert (!image_is_dynamic (image));
10543 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10548 * mono_class_get_fields_lazy:
10549 * @klass: the MonoClass to act on
10551 * This routine is an iterator routine for retrieving the fields in a class.
10552 * Only minimal information about fields are loaded. Accessors must be used
10553 * for all MonoClassField returned.
10555 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10556 * iterate over all of the elements. When no more values are
10557 * available, the return value is NULL.
10559 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10562 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10564 MonoClassField* field;
10568 mono_class_setup_basic_field_info (klass);
10569 if (!klass->fields)
10571 /* start from the first */
10572 if (mono_class_get_field_count (klass)) {
10573 *iter = &klass->fields [0];
10574 return (MonoClassField *)*iter;
10580 field = (MonoClassField *)*iter;
10582 if (field < &klass->fields [mono_class_get_field_count (klass)]) {
10584 return (MonoClassField *)*iter;
10590 mono_class_full_name (MonoClass *klass)
10592 return mono_type_full_name (&klass->byval_arg);
10595 /* Declare all shared lazy type lookup functions */
10596 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, System.Runtime.InteropServices, SafeHandle)