2 * class.c: Class management for the Mono runtime
5 * Miguel de Icaza (miguel@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9 * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
10 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
20 #include <mono/metadata/image.h>
21 #include <mono/metadata/image-internals.h>
22 #include <mono/metadata/assembly.h>
23 #include <mono/metadata/assembly-internals.h>
24 #include <mono/metadata/metadata.h>
25 #include <mono/metadata/metadata-internals.h>
26 #include <mono/metadata/profiler-private.h>
27 #include <mono/metadata/tabledefs.h>
28 #include <mono/metadata/tokentype.h>
29 #include <mono/metadata/class-internals.h>
30 #include <mono/metadata/object.h>
31 #include <mono/metadata/appdomain.h>
32 #include <mono/metadata/mono-endian.h>
33 #include <mono/metadata/debug-helpers.h>
34 #include <mono/metadata/reflection.h>
35 #include <mono/metadata/exception.h>
36 #include <mono/metadata/security-manager.h>
37 #include <mono/metadata/security-core-clr.h>
38 #include <mono/metadata/attrdefs.h>
39 #include <mono/metadata/gc-internals.h>
40 #include <mono/metadata/verify-internals.h>
41 #include <mono/metadata/mono-debug.h>
42 #include <mono/utils/mono-counters.h>
43 #include <mono/utils/mono-string.h>
44 #include <mono/utils/mono-error-internals.h>
45 #include <mono/utils/mono-logger-internals.h>
46 #include <mono/utils/mono-memory-model.h>
47 #include <mono/utils/atomic.h>
48 #include <mono/utils/bsearch.h>
49 #include <mono/utils/checked-build.h>
53 gboolean mono_print_vtable = FALSE;
54 gboolean mono_align_small_structs = FALSE;
57 guint32 inflated_classes_size, inflated_methods_size;
58 guint32 classes_size, class_ext_size, class_ext_count;
59 guint32 class_def_count, class_gtd_count, class_ginst_count, class_gparam_count, class_array_count, class_pointer_count;
61 /* Low level lock which protects data structures in this module */
62 static mono_mutex_t classes_mutex;
64 /* Function supplied by the runtime to find classes by name using information from the AOT file */
65 static MonoGetClassFromName get_class_from_name = NULL;
67 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error);
68 static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
69 static gboolean can_access_type (MonoClass *access_klass, MonoClass *member_klass);
70 static MonoMethod* find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags);
71 static int generic_array_methods (MonoClass *klass);
72 static void setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos);
74 static MonoMethod* mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter);
75 static char* mono_assembly_name_from_token (MonoImage *image, guint32 type_token);
76 static void mono_field_resolve_type (MonoClassField *field, MonoError *error);
77 static guint32 mono_field_resolve_flags (MonoClassField *field);
78 static void mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup);
79 static void mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gklass);
81 static gboolean mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error);
85 We use gclass recording to allow recursive system f types to be referenced by a parent.
87 Given the following type hierarchy:
89 class TextBox : TextBoxBase<TextBox> {}
90 class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
91 class TextInput<T> : Input<T> where T: TextInput<T> {}
94 The runtime tries to load TextBoxBase<>.
95 To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
96 To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
97 To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
99 At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded
100 at this point, iow, both are registered in the type map and both and a NULL parent. This means
101 that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
103 To fix that what we do is to record all generic instantes created while resolving the parent of
104 any generic type definition and, after resolved, correct the parent field if needed.
107 static int record_gclass_instantiation;
108 static GSList *gclass_recorded_list;
109 typedef gboolean (*gclass_record_func) (MonoClass*, void*);
111 /* This TLS variable points to a GSList of classes which have setup_fields () executing */
112 static MonoNativeTlsKey setup_fields_tls_id;
114 static MonoNativeTlsKey init_pending_tls_id;
119 mono_locks_os_acquire (&classes_mutex, ClassesLock);
123 classes_unlock (void)
125 mono_locks_os_release (&classes_mutex, ClassesLock);
129 * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
132 enable_gclass_recording (void)
134 ++record_gclass_instantiation;
138 * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
141 disable_gclass_recording (gclass_record_func func, void *user_data)
143 GSList **head = &gclass_recorded_list;
145 g_assert (record_gclass_instantiation > 0);
146 --record_gclass_instantiation;
149 GSList *node = *head;
150 if (func ((MonoClass*)node->data, user_data)) {
152 g_slist_free_1 (node);
158 /* We automatically discard all recorded gclasses when disabled. */
159 if (!record_gclass_instantiation && gclass_recorded_list) {
160 g_slist_free (gclass_recorded_list);
161 gclass_recorded_list = NULL;
166 * mono_class_from_typeref:
167 * @image: a MonoImage
168 * @type_token: a TypeRef token
170 * Creates the MonoClass* structure representing the type defined by
171 * the typeref token valid inside @image.
172 * Returns: The MonoClass* representing the typeref token, NULL ifcould
176 mono_class_from_typeref (MonoImage *image, guint32 type_token)
179 MonoClass *klass = mono_class_from_typeref_checked (image, type_token, &error);
180 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
185 * mono_class_from_typeref_checked:
186 * @image: a MonoImage
187 * @type_token: a TypeRef token
188 * @error: error return code, if any.
190 * Creates the MonoClass* structure representing the type defined by
191 * the typeref token valid inside @image.
193 * Returns: The MonoClass* representing the typeref token, NULL if it could
194 * not be loaded with the @error value filled with the information about the
198 mono_class_from_typeref_checked (MonoImage *image, guint32 type_token, MonoError *error)
200 guint32 cols [MONO_TYPEREF_SIZE];
201 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
203 const char *name, *nspace;
204 MonoClass *res = NULL;
207 mono_error_init (error);
209 if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, error))
212 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
214 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
215 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
217 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
218 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
219 case MONO_RESOLUTION_SCOPE_MODULE:
221 LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
222 This is not the observed behavior of existing implementations.
223 The defacto behavior is that it's just a typedef in disguise.
225 /* a typedef in disguise */
226 res = mono_class_from_name_checked (image, nspace, name, error);
229 case MONO_RESOLUTION_SCOPE_MODULEREF:
230 module = mono_image_load_module_checked (image, idx, error);
232 res = mono_class_from_name_checked (module, nspace, name, error);
235 case MONO_RESOLUTION_SCOPE_TYPEREF: {
236 MonoClass *enclosing;
239 if (idx == mono_metadata_token_index (type_token)) {
240 mono_error_set_bad_image (error, image, "Image with self-referencing typeref token %08x.", type_token);
244 enclosing = mono_class_from_typeref_checked (image, MONO_TOKEN_TYPE_REF | idx, error);
245 return_val_if_nok (error, NULL);
247 GList *nested_classes = mono_class_get_nested_classes_property (enclosing);
248 if (enclosing->nested_classes_inited && nested_classes) {
249 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
250 for (tmp = nested_classes; tmp; tmp = tmp->next) {
251 res = (MonoClass *)tmp->data;
252 if (strcmp (res->name, name) == 0)
256 /* Don't call mono_class_init as we might've been called by it recursively */
257 int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
259 guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
260 guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
261 const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
263 if (strcmp (nname, name) == 0)
264 return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, error);
266 i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
269 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name);
272 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
276 if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) {
277 mono_error_set_bad_image (error, image, "Image with invalid assemblyref token %08x.", idx);
281 if (!image->references || !image->references [idx - 1])
282 mono_assembly_load_reference (image, idx - 1);
283 g_assert (image->references [idx - 1]);
285 /* If the assembly did not load, register this as a type load exception */
286 if (image->references [idx - 1] == REFERENCE_MISSING){
287 MonoAssemblyName aname;
290 mono_assembly_get_assemblyref (image, idx - 1, &aname);
291 human_name = mono_stringify_assembly_name (&aname);
292 mono_error_set_assembly_load_simple (error, human_name, image->assembly ? image->assembly->ref_only : FALSE);
296 res = mono_class_from_name_checked (image->references [idx - 1]->image, nspace, name, error);
299 /* Generic case, should be avoided for when a better error is possible. */
300 if (!res && mono_error_ok (error)) {
301 char *name = mono_class_name_from_token (image, type_token);
302 char *assembly = mono_assembly_name_from_token (image, type_token);
303 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
310 mono_image_memdup (MonoImage *image, void *data, guint size)
312 void *res = mono_image_alloc (image, size);
313 memcpy (res, data, size);
317 /* Copy everything mono_metadata_free_array free. */
319 mono_dup_array_type (MonoImage *image, MonoArrayType *a)
322 a = (MonoArrayType *)mono_image_memdup (image, a, sizeof (MonoArrayType));
324 a->sizes = (int *)mono_image_memdup (image, a->sizes, a->numsizes * sizeof (int));
326 a->lobounds = (int *)mono_image_memdup (image, a->lobounds, a->numlobounds * sizeof (int));
328 a = (MonoArrayType *)g_memdup (a, sizeof (MonoArrayType));
330 a->sizes = (int *)g_memdup (a->sizes, a->numsizes * sizeof (int));
332 a->lobounds = (int *)g_memdup (a->lobounds, a->numlobounds * sizeof (int));
337 /* Copy everything mono_metadata_free_method_signature free. */
339 mono_metadata_signature_deep_dup (MonoImage *image, MonoMethodSignature *sig)
343 sig = mono_metadata_signature_dup_full (image, sig);
345 sig->ret = mono_metadata_type_dup (image, sig->ret);
346 for (i = 0; i < sig->param_count; ++i)
347 sig->params [i] = mono_metadata_type_dup (image, sig->params [i]);
353 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
355 MonoAssembly *ta = klass->image->assembly;
358 name = mono_stringify_assembly_name (&ta->aname);
359 g_string_append_printf (str, ", %s", name);
364 mono_type_name_check_byref (MonoType *type, GString *str)
367 g_string_append_c (str, '&');
371 * mono_identifier_escape_type_name_chars:
372 * @str: a destination string
373 * @identifier: an IDENTIFIER in internal form
377 * The displayed form of the identifier is appended to str.
379 * The displayed form of an identifier has the characters ,+&*[]\
380 * that have special meaning in type names escaped with a preceeding
381 * backslash (\) character.
384 mono_identifier_escape_type_name_chars (GString* str, const char* identifier)
390 // reserve space for common case: there will be no escaped characters.
391 g_string_set_size(str, n + strlen(identifier));
392 g_string_set_size(str, n);
394 for (const char* s = identifier; *s != 0 ; s++) {
403 g_string_append_c (str, '\\');
404 g_string_append_c (str, *s);
407 g_string_append_c (str, *s);
415 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
416 MonoTypeNameFormat format)
420 switch (type->type) {
421 case MONO_TYPE_ARRAY: {
422 int i, rank = type->data.array->rank;
423 MonoTypeNameFormat nested_format;
425 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
426 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
428 mono_type_get_name_recurse (
429 &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
430 g_string_append_c (str, '[');
432 g_string_append_c (str, '*');
433 for (i = 1; i < rank; i++)
434 g_string_append_c (str, ',');
435 g_string_append_c (str, ']');
437 mono_type_name_check_byref (type, str);
439 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
440 _mono_type_get_assembly_name (type->data.array->eklass, str);
443 case MONO_TYPE_SZARRAY: {
444 MonoTypeNameFormat nested_format;
446 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
447 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
449 mono_type_get_name_recurse (
450 &type->data.klass->byval_arg, str, FALSE, nested_format);
451 g_string_append (str, "[]");
453 mono_type_name_check_byref (type, str);
455 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
456 _mono_type_get_assembly_name (type->data.klass, str);
459 case MONO_TYPE_PTR: {
460 MonoTypeNameFormat nested_format;
462 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
463 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
465 mono_type_get_name_recurse (
466 type->data.type, str, FALSE, nested_format);
467 g_string_append_c (str, '*');
469 mono_type_name_check_byref (type, str);
471 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
472 _mono_type_get_assembly_name (mono_class_from_mono_type (type->data.type), str);
477 if (!mono_generic_param_info (type->data.generic_param))
478 g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num);
480 g_string_append (str, mono_generic_param_info (type->data.generic_param)->name);
482 mono_type_name_check_byref (type, str);
486 klass = mono_class_from_mono_type (type);
487 if (klass->nested_in) {
488 mono_type_get_name_recurse (
489 &klass->nested_in->byval_arg, str, TRUE, format);
490 if (format == MONO_TYPE_NAME_FORMAT_IL)
491 g_string_append_c (str, '.');
493 g_string_append_c (str, '+');
494 } else if (*klass->name_space) {
495 if (format == MONO_TYPE_NAME_FORMAT_IL)
496 g_string_append (str, klass->name_space);
498 mono_identifier_escape_type_name_chars (str, klass->name_space);
499 g_string_append_c (str, '.');
501 if (format == MONO_TYPE_NAME_FORMAT_IL) {
502 char *s = strchr (klass->name, '`');
503 int len = s ? s - klass->name : strlen (klass->name);
504 g_string_append_len (str, klass->name, len);
506 mono_identifier_escape_type_name_chars (str, klass->name);
510 if (mono_class_is_ginst (klass)) {
511 MonoGenericClass *gclass = mono_class_get_generic_class (klass);
512 MonoGenericInst *inst = gclass->context.class_inst;
513 MonoTypeNameFormat nested_format;
516 nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
517 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
519 if (format == MONO_TYPE_NAME_FORMAT_IL)
520 g_string_append_c (str, '<');
522 g_string_append_c (str, '[');
523 for (i = 0; i < inst->type_argc; i++) {
524 MonoType *t = inst->type_argv [i];
527 g_string_append_c (str, ',');
528 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
529 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
530 g_string_append_c (str, '[');
531 mono_type_get_name_recurse (inst->type_argv [i], str, FALSE, nested_format);
532 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
533 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
534 g_string_append_c (str, ']');
536 if (format == MONO_TYPE_NAME_FORMAT_IL)
537 g_string_append_c (str, '>');
539 g_string_append_c (str, ']');
540 } else if (mono_class_is_gtd (klass) &&
541 (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
542 (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
545 if (format == MONO_TYPE_NAME_FORMAT_IL)
546 g_string_append_c (str, '<');
548 g_string_append_c (str, '[');
549 for (i = 0; i < mono_class_get_generic_container (klass)->type_argc; i++) {
551 g_string_append_c (str, ',');
552 g_string_append (str, mono_generic_container_get_param_info (mono_class_get_generic_container (klass), i)->name);
554 if (format == MONO_TYPE_NAME_FORMAT_IL)
555 g_string_append_c (str, '>');
557 g_string_append_c (str, ']');
560 mono_type_name_check_byref (type, str);
562 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
563 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
564 _mono_type_get_assembly_name (klass, str);
570 * mono_type_get_name_full:
572 * @format: the format for the return string.
575 * Returns: The string representation in a number of formats:
577 * if format is MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
578 * returned in the formatrequired by System.Reflection, this is the
579 * inverse of mono_reflection_parse_type ().
581 * if format is MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
582 * be used by the IL assembler.
584 * if format is MONO_TYPE_NAME_FORMAT_FULL_NAME
586 * if format is MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
589 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
593 result = g_string_new ("");
595 mono_type_get_name_recurse (type, result, FALSE, format);
597 return g_string_free (result, FALSE);
601 * mono_type_get_full_name:
604 * Returns: The string representation for type as required by System.Reflection.
605 * The inverse of mono_reflection_parse_type ().
608 mono_type_get_full_name (MonoClass *klass)
610 return mono_type_get_name_full (mono_class_get_type (klass), MONO_TYPE_NAME_FORMAT_REFLECTION);
614 * mono_type_get_name:
617 * Returns: The string representation for type as it would be represented in IL code.
620 mono_type_get_name (MonoType *type)
622 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
626 * mono_type_get_underlying_type:
629 * Returns: The MonoType for the underlying integer type if @type
630 * is an enum and byref is false, otherwise the type itself.
633 mono_type_get_underlying_type (MonoType *type)
635 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype && !type->byref)
636 return mono_class_enum_basetype (type->data.klass);
637 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype && !type->byref)
638 return mono_class_enum_basetype (type->data.generic_class->container_class);
643 * mono_class_is_open_constructed_type:
646 * Returns: TRUE if type represents a generics open constructed type.
647 * IOW, not all type parameters required for the instantiation have
648 * been provided or it's a generic type definition.
650 * An open constructed type means it's a non realizable type. Not to
651 * be mixed up with an abstract type - we can't cast or dispatch to
652 * an open type, for example.
655 mono_class_is_open_constructed_type (MonoType *t)
661 case MONO_TYPE_SZARRAY:
662 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
663 case MONO_TYPE_ARRAY:
664 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
666 return mono_class_is_open_constructed_type (t->data.type);
667 case MONO_TYPE_GENERICINST:
668 return t->data.generic_class->context.class_inst->is_open;
669 case MONO_TYPE_CLASS:
670 case MONO_TYPE_VALUETYPE:
671 return mono_class_is_gtd (t->data.klass);
678 This is a simple function to catch the most common bad instances of generic types.
679 Specially those that might lead to further failures in the runtime.
682 is_valid_generic_argument (MonoType *type)
684 switch (type->type) {
686 //case MONO_TYPE_TYPEDBYREF:
694 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
696 mono_error_init (error);
698 switch (type->type) {
699 case MONO_TYPE_MVAR: {
701 int num = mono_type_get_generic_param_num (type);
702 MonoGenericInst *inst = context->method_inst;
705 if (num >= inst->type_argc) {
706 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
707 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
708 num, info ? info->name : "", inst->type_argc);
712 if (!is_valid_generic_argument (inst->type_argv [num])) {
713 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
714 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
715 num, info ? info->name : "", inst->type_argv [num]->type);
719 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
720 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
721 * ->byref and ->attrs from @type are propagated to the returned type.
723 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
724 nt->byref = type->byref;
725 nt->attrs = type->attrs;
728 case MONO_TYPE_VAR: {
730 int num = mono_type_get_generic_param_num (type);
731 MonoGenericInst *inst = context->class_inst;
734 if (num >= inst->type_argc) {
735 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
736 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
737 num, info ? info->name : "", inst->type_argc);
740 if (!is_valid_generic_argument (inst->type_argv [num])) {
741 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
742 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
743 num, info ? info->name : "", inst->type_argv [num]->type);
746 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
747 nt->byref = type->byref;
748 nt->attrs = type->attrs;
751 case MONO_TYPE_SZARRAY: {
752 MonoClass *eclass = type->data.klass;
753 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
754 if (!inflated || !mono_error_ok (error))
756 nt = mono_metadata_type_dup (image, type);
757 nt->data.klass = mono_class_from_mono_type (inflated);
758 mono_metadata_free_type (inflated);
761 case MONO_TYPE_ARRAY: {
762 MonoClass *eclass = type->data.array->eklass;
763 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
764 if (!inflated || !mono_error_ok (error))
766 nt = mono_metadata_type_dup (image, type);
767 nt->data.array->eklass = mono_class_from_mono_type (inflated);
768 mono_metadata_free_type (inflated);
771 case MONO_TYPE_GENERICINST: {
772 MonoGenericClass *gclass = type->data.generic_class;
773 MonoGenericInst *inst;
775 if (!gclass->context.class_inst->is_open)
778 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
779 return_val_if_nok (error, NULL);
781 if (inst != gclass->context.class_inst)
782 gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
784 if (gclass == type->data.generic_class)
787 nt = mono_metadata_type_dup (image, type);
788 nt->data.generic_class = gclass;
791 case MONO_TYPE_CLASS:
792 case MONO_TYPE_VALUETYPE: {
793 MonoClass *klass = type->data.klass;
794 MonoGenericContainer *container = mono_class_try_get_generic_container (klass);
795 MonoGenericInst *inst;
796 MonoGenericClass *gclass = NULL;
802 /* We can't use context->class_inst directly, since it can have more elements */
803 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
804 return_val_if_nok (error, NULL);
806 if (inst == container->context.class_inst)
809 gclass = mono_metadata_lookup_generic_class (klass, inst, image_is_dynamic (klass->image));
811 nt = mono_metadata_type_dup (image, type);
812 nt->type = MONO_TYPE_GENERICINST;
813 nt->data.generic_class = gclass;
823 mono_generic_class_get_context (MonoGenericClass *gclass)
825 return &gclass->context;
829 mono_class_get_context (MonoClass *klass)
831 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
832 return gklass ? mono_generic_class_get_context (gklass) : NULL;
836 * mono_class_inflate_generic_type_with_mempool:
837 * @mempool: a mempool
839 * @context: a generics context
840 * @error: error context
842 * The same as mono_class_inflate_generic_type, but allocates the MonoType
843 * from mempool if it is non-NULL. If it is NULL, the MonoType is
844 * allocated on the heap and is owned by the caller.
845 * The returned type can potentially be the same as TYPE, so it should not be
846 * modified by the caller, and it should be freed using mono_metadata_free_type ().
849 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
851 MonoType *inflated = NULL;
852 mono_error_init (error);
855 inflated = inflate_generic_type (image, type, context, error);
856 return_val_if_nok (error, NULL);
859 MonoType *shared = mono_metadata_get_shared_type (type);
864 return mono_metadata_type_dup (image, type);
868 mono_stats.inflated_type_count++;
873 * mono_class_inflate_generic_type:
875 * @context: a generics context
877 * If @type is a generic type and @context is not NULL, instantiate it using the
878 * generics context @context.
880 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
881 * on the heap and is owned by the caller. Returns NULL on error.
883 * @deprecated Please use mono_class_inflate_generic_type_checked instead
886 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
890 result = mono_class_inflate_generic_type_checked (type, context, &error);
891 mono_error_cleanup (&error);
896 * mono_class_inflate_generic_type:
898 * @context: a generics context
899 * @error: error context to use
901 * If @type is a generic type and @context is not NULL, instantiate it using the
902 * generics context @context.
904 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
905 * on the heap and is owned by the caller.
908 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
910 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
914 * mono_class_inflate_generic_type_no_copy:
916 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
920 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
922 MonoType *inflated = NULL;
924 mono_error_init (error);
926 inflated = inflate_generic_type (image, type, context, error);
927 return_val_if_nok (error, NULL);
933 mono_stats.inflated_type_count++;
938 * mono_class_inflate_generic_class:
940 * Inflate the class @gklass with @context. Set @error on failure.
943 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
948 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
949 return_val_if_nok (error, NULL);
951 res = mono_class_from_mono_type (inflated);
952 mono_metadata_free_type (inflated);
957 static MonoGenericContext
958 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
960 MonoGenericInst *class_inst = NULL;
961 MonoGenericInst *method_inst = NULL;
962 MonoGenericContext res = { NULL, NULL };
964 mono_error_init (error);
966 if (context->class_inst) {
967 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
968 if (!mono_error_ok (error))
972 if (context->method_inst) {
973 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
974 if (!mono_error_ok (error))
978 res.class_inst = class_inst;
979 res.method_inst = method_inst;
985 * mono_class_inflate_generic_method:
986 * @method: a generic method
987 * @context: a generics context
989 * Instantiate the generic method @method using the generics context @context.
991 * Returns: The new instantiated method
994 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
996 return mono_class_inflate_generic_method_full (method, NULL, context);
1000 mono_class_inflate_generic_method_checked (MonoMethod *method, MonoGenericContext *context, MonoError *error)
1002 return mono_class_inflate_generic_method_full_checked (method, NULL, context, error);
1006 * mono_class_inflate_generic_method_full:
1008 * Instantiate method @method with the generic context @context.
1009 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
1010 * Use mono_method_signature () and mono_method_get_header () to get the correct values.
1013 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
1016 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
1017 if (!mono_error_ok (&error))
1018 /*FIXME do proper error handling - on this case, kill this function. */
1019 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
1025 * mono_class_inflate_generic_method_full_checked:
1026 * Same as mono_class_inflate_generic_method_full but return failure using @error.
1029 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
1032 MonoMethodInflated *iresult, *cached;
1033 MonoMethodSignature *sig;
1034 MonoGenericContext tmp_context;
1036 mono_error_init (error);
1038 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1039 while (method->is_inflated) {
1040 MonoGenericContext *method_context = mono_method_get_context (method);
1041 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1043 tmp_context = inflate_generic_context (method_context, context, error);
1044 return_val_if_nok (error, NULL);
1046 context = &tmp_context;
1048 if (mono_metadata_generic_context_equal (method_context, context))
1051 method = imethod->declaring;
1055 * A method only needs to be inflated if the context has argument for which it is
1058 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1059 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1062 if (!((method->is_generic && context->method_inst) ||
1063 (mono_class_is_gtd (method->klass) && context->class_inst)))
1066 iresult = g_new0 (MonoMethodInflated, 1);
1067 iresult->context = *context;
1068 iresult->declaring = method;
1070 if (!context->method_inst && method->is_generic)
1071 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1073 if (!context->class_inst) {
1074 g_assert (!mono_class_is_ginst (iresult->declaring->klass));
1075 if (mono_class_is_gtd (iresult->declaring->klass))
1076 iresult->context.class_inst = mono_class_get_generic_container (iresult->declaring->klass)->context.class_inst;
1078 /* This can happen with some callers like mono_object_get_virtual_method () */
1079 if (!mono_class_is_gtd (iresult->declaring->klass) && !mono_class_is_ginst (iresult->declaring->klass))
1080 iresult->context.class_inst = NULL;
1082 MonoImageSet *set = mono_metadata_get_image_set_for_method (iresult);
1085 mono_image_set_lock (set);
1086 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1087 mono_image_set_unlock (set);
1091 return (MonoMethod*)cached;
1094 mono_stats.inflated_method_count++;
1096 inflated_methods_size += sizeof (MonoMethodInflated);
1098 sig = mono_method_signature (method);
1100 char *name = mono_type_get_full_name (method->klass);
1101 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1107 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1109 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1112 result = (MonoMethod *) iresult;
1113 result->is_inflated = TRUE;
1114 result->is_generic = FALSE;
1115 result->sre_method = FALSE;
1116 result->signature = NULL;
1118 if (method->wrapper_type) {
1119 MonoMethodWrapper *mw = (MonoMethodWrapper*)method;
1120 MonoMethodWrapper *resw = (MonoMethodWrapper*)result;
1121 int len = GPOINTER_TO_INT (((void**)mw->method_data) [0]);
1123 resw->method_data = (void **)g_malloc (sizeof (gpointer) * (len + 1));
1124 memcpy (resw->method_data, mw->method_data, sizeof (gpointer) * (len + 1));
1127 if (iresult->context.method_inst) {
1128 /* Set the generic_container of the result to the generic_container of method */
1129 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1131 if (generic_container && iresult->context.method_inst == generic_container->context.method_inst) {
1132 result->is_generic = 1;
1133 mono_method_set_generic_container (result, generic_container);
1138 MonoGenericClass *gklass_hint = mono_class_try_get_generic_class (klass_hint);
1139 if (gklass_hint && (gklass_hint->container_class != method->klass || gklass_hint->context.class_inst != context->class_inst))
1143 if (mono_class_is_gtd (method->klass))
1144 result->klass = klass_hint;
1146 if (!result->klass) {
1147 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1148 if (!mono_error_ok (error))
1151 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1153 mono_metadata_free_type (inflated);
1157 * FIXME: This should hold, but it doesn't:
1159 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1160 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1161 * g_assert (result->is_generic);
1164 * Fixing this here causes other things to break, hence a very
1165 * ugly hack in mini-trampolines.c - see
1166 * is_generic_method_definition().
1170 mono_image_set_lock (set);
1171 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1173 g_hash_table_insert (set->gmethod_cache, iresult, iresult);
1174 iresult->owner = set;
1177 mono_image_set_unlock (set);
1179 return (MonoMethod*)cached;
1187 * mono_get_inflated_method:
1189 * Obsolete. We keep it around since it's mentioned in the public API.
1192 mono_get_inflated_method (MonoMethod *method)
1198 * mono_method_get_context_general:
1200 * @uninflated: handle uninflated methods?
1202 * Returns the generic context of a method or NULL if it doesn't have
1203 * one. For an inflated method that's the context stored in the
1204 * method. Otherwise it's in the method's generic container or in the
1205 * generic container of the method's class.
1208 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1210 if (method->is_inflated) {
1211 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1212 return &imethod->context;
1216 if (method->is_generic)
1217 return &(mono_method_get_generic_container (method)->context);
1218 if (mono_class_is_gtd (method->klass))
1219 return &mono_class_get_generic_container (method->klass)->context;
1224 * mono_method_get_context:
1227 * Returns the generic context for method if it's inflated, otherwise
1231 mono_method_get_context (MonoMethod *method)
1233 return mono_method_get_context_general (method, FALSE);
1237 * mono_method_get_generic_container:
1239 * Returns the generic container of METHOD, which should be a generic method definition.
1240 * Returns NULL if METHOD is not a generic method definition.
1241 * LOCKING: Acquires the loader lock.
1243 MonoGenericContainer*
1244 mono_method_get_generic_container (MonoMethod *method)
1246 MonoGenericContainer *container;
1248 if (!method->is_generic)
1251 container = (MonoGenericContainer *)mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1252 g_assert (container);
1258 * mono_method_set_generic_container:
1260 * Sets the generic container of METHOD to CONTAINER.
1261 * LOCKING: Acquires the image lock.
1264 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1266 g_assert (method->is_generic);
1268 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1272 * mono_class_find_enum_basetype:
1273 * @class: The enum class
1275 * Determine the basetype of an enum by iterating through its fields. We do this
1276 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1279 mono_class_find_enum_basetype (MonoClass *klass, MonoError *error)
1281 MonoGenericContainer *container = NULL;
1282 MonoImage *m = klass->image;
1283 const int top = mono_class_get_field_count (klass);
1284 int i, first_field_idx;
1286 g_assert (klass->enumtype);
1288 mono_error_init (error);
1290 container = mono_class_try_get_generic_container (klass);
1291 if (mono_class_is_ginst (klass)) {
1292 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
1294 container = mono_class_get_generic_container (gklass);
1295 g_assert (container);
1299 * Fetch all the field information.
1301 first_field_idx = mono_class_get_first_field_idx (klass);
1302 for (i = 0; i < top; i++){
1304 guint32 cols [MONO_FIELD_SIZE];
1305 int idx = first_field_idx + i;
1308 /* first_field_idx and idx points into the fieldptr table */
1309 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1311 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1314 if (!mono_verifier_verify_field_signature (klass->image, cols [MONO_FIELD_SIGNATURE], NULL)) {
1315 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x", cols [MONO_FIELD_SIGNATURE]);
1319 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1320 mono_metadata_decode_value (sig, &sig);
1321 /* FIELD signature == 0x06 */
1323 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig);
1327 ftype = mono_metadata_parse_type_checked (m, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
1331 if (mono_class_is_ginst (klass)) {
1332 //FIXME do we leak here?
1333 ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (klass), error);
1334 if (!mono_error_ok (error))
1336 ftype->attrs = cols [MONO_FIELD_FLAGS];
1341 mono_error_set_type_load_class (error, klass, "Could not find base type");
1348 * Checks for MonoClass::has_failure without resolving all MonoType's into MonoClass'es
1351 mono_type_has_exceptions (MonoType *type)
1353 switch (type->type) {
1354 case MONO_TYPE_CLASS:
1355 case MONO_TYPE_VALUETYPE:
1356 case MONO_TYPE_SZARRAY:
1357 return mono_class_has_failure (type->data.klass);
1358 case MONO_TYPE_ARRAY:
1359 return mono_class_has_failure (type->data.array->eklass);
1360 case MONO_TYPE_GENERICINST:
1361 return mono_class_has_failure (mono_generic_class_get_class (type->data.generic_class));
1368 mono_error_set_for_class_failure (MonoError *oerror, const MonoClass *klass)
1370 g_assert (mono_class_has_failure (klass));
1371 MonoErrorBoxed *box = mono_class_get_exception_data ((MonoClass*)klass);
1372 mono_error_set_from_boxed (oerror, box);
1378 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1382 mono_class_alloc (MonoClass *klass, int size)
1384 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
1386 return mono_image_set_alloc (gklass->owner, size);
1388 return mono_image_alloc (klass->image, size);
1392 mono_class_alloc0 (MonoClass *klass, int size)
1396 res = mono_class_alloc (klass, size);
1397 memset (res, 0, size);
1401 #define mono_class_new0(klass,struct_type, n_structs) \
1402 ((struct_type *) mono_class_alloc0 ((klass), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1405 * mono_class_setup_basic_field_info:
1406 * @class: The class to initialize
1408 * Initializes the following fields in MonoClass:
1409 * * klass->fields (only field->parent and field->name)
1410 * * klass->field.count
1411 * * klass->first_field_idx
1412 * LOCKING: Acquires the loader lock
1415 mono_class_setup_basic_field_info (MonoClass *klass)
1417 MonoGenericClass *gklass;
1418 MonoClassField *field;
1419 MonoClassField *fields;
1427 gklass = mono_class_try_get_generic_class (klass);
1428 gtd = gklass ? mono_class_get_generic_type_definition (klass) : NULL;
1429 image = klass->image;
1432 if (gklass && image_is_dynamic (gklass->container_class->image) && !gklass->container_class->wastypebuilder) {
1434 * This happens when a generic instance of an unfinished generic typebuilder
1435 * is used as an element type for creating an array type. We can't initialize
1436 * the fields of this class using the fields of gklass, since gklass is not
1437 * finished yet, fields could be added to it later.
1443 mono_class_setup_basic_field_info (gtd);
1445 mono_loader_lock ();
1446 mono_class_set_field_count (klass, mono_class_get_field_count (gtd));
1447 mono_loader_unlock ();
1450 top = mono_class_get_field_count (klass);
1452 fields = (MonoClassField *)mono_class_alloc0 (klass, sizeof (MonoClassField) * top);
1455 * Fetch all the field information.
1457 int first_field_idx = mono_class_has_static_metadata (klass) ? mono_class_get_first_field_idx (klass) : 0;
1458 for (i = 0; i < top; i++) {
1459 field = &fields [i];
1460 field->parent = klass;
1463 field->name = mono_field_get_name (>d->fields [i]);
1465 int idx = first_field_idx + i;
1466 /* first_field_idx and idx points into the fieldptr table */
1467 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1468 /* The name is needed for fieldrefs */
1469 field->name = mono_metadata_string_heap (image, name_idx);
1473 mono_memory_barrier ();
1475 mono_loader_lock ();
1477 klass->fields = fields;
1478 mono_loader_unlock ();
1482 * mono_class_set_failure_causedby_class:
1483 * @klass: the class that is failing
1484 * @caused_by: the class that caused the failure
1485 * @msg: Why @klass is failing.
1487 * If @caused_by has a failure, sets a TypeLoadException failure on
1488 * @klass with message "@msg, due to: {@caused_by message}".
1490 * Returns: TRUE if a failiure was set, or FALSE if @caused_by doesn't have a failure.
1493 mono_class_set_type_load_failure_causedby_class (MonoClass *klass, const MonoClass *caused_by, const gchar* msg)
1495 if (mono_class_has_failure (caused_by)) {
1496 MonoError cause_error;
1497 mono_error_init (&cause_error);
1498 mono_error_set_for_class_failure (&cause_error, caused_by);
1499 mono_class_set_type_load_failure (klass, "%s, due to: %s", msg, mono_error_get_message (&cause_error));
1500 mono_error_cleanup (&cause_error);
1509 * mono_class_setup_fields:
1510 * @klass: The class to initialize
1512 * Initializes klass->fields, computes class layout and sizes.
1513 * typebuilder_setup_fields () is the corresponding function for dynamic classes.
1514 * Sets the following fields in @klass:
1515 * - all the fields initialized by mono_class_init_sizes ()
1516 * - element_class/cast_class (for enums)
1517 * - field->type/offset for all fields
1520 * LOCKING: Acquires the loader lock.
1523 mono_class_setup_fields (MonoClass *klass)
1526 MonoImage *m = klass->image;
1528 guint32 layout = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK;
1530 guint32 real_size = 0;
1531 guint32 packing_size = 0;
1533 gboolean explicit_size;
1534 MonoClassField *field;
1535 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
1536 MonoClass *gtd = gklass ? mono_class_get_generic_type_definition (klass) : NULL;
1538 if (klass->fields_inited)
1541 if (gklass && image_is_dynamic (gklass->container_class->image) && !gklass->container_class->wastypebuilder) {
1543 * This happens when a generic instance of an unfinished generic typebuilder
1544 * is used as an element type for creating an array type. We can't initialize
1545 * the fields of this class using the fields of gklass, since gklass is not
1546 * finished yet, fields could be added to it later.
1551 mono_class_setup_basic_field_info (klass);
1552 top = mono_class_get_field_count (klass);
1555 mono_class_setup_fields (gtd);
1556 if (mono_class_set_type_load_failure_causedby_class (klass, gtd, "Generic type definition failed"))
1561 if (klass->parent) {
1562 /* For generic instances, klass->parent might not have been initialized */
1563 mono_class_init (klass->parent);
1564 mono_class_setup_fields (klass->parent);
1565 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Could not set up parent class"))
1567 instance_size = klass->parent->instance_size;
1569 instance_size = sizeof (MonoObject);
1572 /* Get the real size */
1573 explicit_size = mono_metadata_packing_from_typedef (klass->image, klass->type_token, &packing_size, &real_size);
1575 instance_size += real_size;
1578 * This function can recursively call itself.
1579 * Prevent infinite recursion by using a list in TLS.
1581 GSList *init_list = (GSList *)mono_native_tls_get_value (setup_fields_tls_id);
1582 if (g_slist_find (init_list, klass))
1584 init_list = g_slist_prepend (init_list, klass);
1585 mono_native_tls_set_value (setup_fields_tls_id, init_list);
1588 * Fetch all the field information.
1590 int first_field_idx = mono_class_has_static_metadata (klass) ? mono_class_get_first_field_idx (klass) : 0;
1591 for (i = 0; i < top; i++) {
1592 int idx = first_field_idx + i;
1593 field = &klass->fields [i];
1596 mono_field_resolve_type (field, &error);
1597 if (!mono_error_ok (&error)) {
1598 /*mono_field_resolve_type already failed class*/
1599 mono_error_cleanup (&error);
1603 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(klass), field->name);
1604 g_assert (field->type);
1607 if (mono_field_is_deleted (field))
1609 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1611 mono_metadata_field_info (m, idx, &uoffset, NULL, NULL);
1612 int offset = uoffset;
1614 if (offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1615 mono_class_set_type_load_failure (klass, "Missing field layout info for %s", field->name);
1618 if (offset < -1) { /*-1 is used to encode special static fields */
1619 mono_class_set_type_load_failure (klass, "Field '%s' has a negative offset %d", field->name, offset);
1622 if (mono_class_is_gtd (klass)) {
1623 mono_class_set_type_load_failure (klass, "Generic class cannot have explicit layout.");
1627 if (mono_type_has_exceptions (field->type)) {
1628 char *class_name = mono_type_get_full_name (klass);
1629 char *type_name = mono_type_full_name (field->type);
1631 mono_class_set_type_load_failure (klass, "");
1632 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1633 g_free (class_name);
1637 /* The def_value of fields is compute lazily during vtable creation */
1640 if (!mono_class_has_failure (klass)) {
1641 mono_loader_lock ();
1642 mono_class_layout_fields (klass, instance_size, packing_size, FALSE);
1643 mono_loader_unlock ();
1646 init_list = g_slist_remove (init_list, klass);
1647 mono_native_tls_set_value (setup_fields_tls_id, init_list);
1651 init_sizes_with_info (MonoClass *klass, MonoCachedClassInfo *cached_info)
1654 klass->instance_size = cached_info->instance_size;
1655 klass->sizes.class_size = cached_info->class_size;
1656 klass->packing_size = cached_info->packing_size;
1657 klass->min_align = cached_info->min_align;
1658 klass->blittable = cached_info->blittable;
1659 klass->has_references = cached_info->has_references;
1660 klass->has_static_refs = cached_info->has_static_refs;
1661 klass->no_special_static_fields = cached_info->no_special_static_fields;
1664 if (!klass->size_inited)
1665 mono_class_setup_fields (klass);
1670 * mono_class_init_sizes:
1672 * Initializes the size related fields of @klass without loading all field data if possible.
1673 * Sets the following fields in @klass:
1675 * - sizes.class_size
1682 * Can fail the class.
1684 * LOCKING: Acquires the loader lock.
1687 mono_class_init_sizes (MonoClass *klass)
1689 MonoCachedClassInfo cached_info;
1690 gboolean has_cached_info;
1692 if (klass->size_inited)
1695 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
1697 init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
1701 * mono_type_get_basic_type_from_generic:
1704 * Returns a closed type corresponding to the possibly open type
1708 mono_type_get_basic_type_from_generic (MonoType *type)
1710 /* When we do generic sharing we let type variables stand for reference/primitive types. */
1711 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) &&
1712 (!type->data.generic_param->gshared_constraint || type->data.generic_param->gshared_constraint->type == MONO_TYPE_OBJECT))
1713 return &mono_defaults.object_class->byval_arg;
1718 class_has_references (MonoClass *klass)
1720 mono_class_init_sizes (klass);
1723 * has_references is not set if this is called recursively, but this is not a problem since this is only used
1724 * during field layout, and instance fields are initialized before static fields, and instance fields can't
1727 return klass->has_references;
1731 type_has_references (MonoClass *klass, MonoType *ftype)
1733 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (klass, ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && class_has_references (mono_class_from_mono_type (ftype)))))
1735 if (!ftype->byref && (ftype->type == MONO_TYPE_VAR || ftype->type == MONO_TYPE_MVAR)) {
1736 MonoGenericParam *gparam = ftype->data.generic_param;
1738 if (gparam->gshared_constraint)
1739 return class_has_references (mono_class_from_mono_type (gparam->gshared_constraint));
1745 * mono_class_layout_fields:
1747 * @base_instance_size: base instance size
1750 * This contains the common code for computing the layout of classes and sizes.
1751 * This should only be called from mono_class_setup_fields () and
1752 * typebuilder_setup_fields ().
1754 * LOCKING: Acquires the loader lock
1757 mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_size, gboolean sre)
1760 const int top = mono_class_get_field_count (klass);
1761 guint32 layout = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK;
1762 guint32 pass, passes, real_size;
1763 gboolean gc_aware_layout = FALSE;
1764 gboolean has_static_fields = FALSE;
1765 gboolean has_references = FALSE;
1766 gboolean has_static_refs = FALSE;
1767 MonoClassField *field;
1769 int instance_size = base_instance_size;
1770 int class_size, min_align;
1772 gboolean *fields_has_references;
1775 * We want to avoid doing complicated work inside locks, so we compute all the required
1776 * information and write it to @klass inside a lock.
1778 if (klass->fields_inited)
1781 if ((packing_size & 0xffffff00) != 0) {
1782 mono_class_set_type_load_failure (klass, "Could not load struct '%s' with packing size %d >= 256", klass->name, packing_size);
1786 if (klass->parent) {
1787 min_align = klass->parent->min_align;
1788 /* we use | since it may have been set already */
1789 has_references = klass->has_references | klass->parent->has_references;
1793 /* We can't really enable 16 bytes alignment until the GC supports it.
1794 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1795 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1796 Bug #506144 is an example of this issue.
1798 if (klass->simd_type)
1803 * When we do generic sharing we need to have layout
1804 * information for open generic classes (either with a generic
1805 * context containing type variables or with a generic
1806 * container), so we don't return in that case anymore.
1809 if (klass->enumtype) {
1810 for (i = 0; i < top; i++) {
1811 field = &klass->fields [i];
1812 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1813 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
1818 if (!mono_class_enum_basetype (klass)) {
1819 mono_class_set_type_load_failure (klass, "The enumeration's base type is invalid.");
1825 * Enable GC aware auto layout: in this mode, reference
1826 * fields are grouped together inside objects, increasing collector
1828 * Requires that all classes whose layout is known to native code be annotated
1829 * with [StructLayout (LayoutKind.Sequential)]
1830 * Value types have gc_aware_layout disabled by default, as per
1831 * what the default is for other runtimes.
1833 /* corlib is missing [StructLayout] directives in many places */
1834 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1835 if (!klass->valuetype)
1836 gc_aware_layout = TRUE;
1839 /* Compute klass->blittable */
1842 blittable = klass->parent->blittable;
1843 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(mono_is_corlib_image (klass->image) && !strcmp (klass->name_space, "System") && !strcmp (klass->name, "ValueType")) && top)
1845 for (i = 0; i < top; i++) {
1846 field = &klass->fields [i];
1848 if (mono_field_is_deleted (field))
1850 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1853 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1856 MonoClass *field_class = mono_class_from_mono_type (field->type);
1858 mono_class_setup_fields (field_class);
1859 if (mono_class_has_failure (field_class)) {
1860 MonoError field_error;
1861 mono_error_init (&field_error);
1862 mono_error_set_for_class_failure (&field_error, field_class);
1863 mono_class_set_type_load_failure (klass, "Could not set up field '%s' due to: %s", field->name, mono_error_get_message (&field_error));
1864 mono_error_cleanup (&field_error);
1868 if (!field_class || !field_class->blittable)
1872 if (klass->enumtype)
1873 blittable = klass->element_class->blittable;
1875 if (mono_class_has_failure (klass))
1877 if (klass == mono_defaults.string_class)
1880 /* Compute klass->has_references */
1882 * Process non-static fields first, since static fields might recursively
1883 * refer to the class itself.
1885 for (i = 0; i < top; i++) {
1888 field = &klass->fields [i];
1890 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1891 ftype = mono_type_get_underlying_type (field->type);
1892 ftype = mono_type_get_basic_type_from_generic (ftype);
1893 if (type_has_references (klass, ftype))
1894 has_references = TRUE;
1899 * Compute field layout and total size (not considering static fields)
1901 field_offsets = g_new0 (int, top);
1902 fields_has_references = g_new0 (gboolean, top);
1903 int first_field_idx = mono_class_has_static_metadata (klass) ? mono_class_get_first_field_idx (klass) : 0;
1905 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1906 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1907 if (gc_aware_layout)
1912 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1915 if (klass->parent) {
1916 mono_class_setup_fields (klass->parent);
1917 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Cannot initialize parent class"))
1919 real_size = klass->parent->instance_size;
1921 real_size = sizeof (MonoObject);
1924 for (pass = 0; pass < passes; ++pass) {
1925 for (i = 0; i < top; i++){
1930 field = &klass->fields [i];
1932 if (mono_field_is_deleted (field))
1934 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1937 ftype = mono_type_get_underlying_type (field->type);
1938 ftype = mono_type_get_basic_type_from_generic (ftype);
1939 if (gc_aware_layout) {
1940 fields_has_references [i] = type_has_references (klass, ftype);
1941 if (fields_has_references [i]) {
1950 if ((top == 1) && (instance_size == sizeof (MonoObject)) &&
1951 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1952 /* This field is a hack inserted by MCS to empty structures */
1956 size = mono_type_size (field->type, &align);
1958 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1959 align = packing_size ? MIN (packing_size, align): align;
1960 /* if the field has managed references, we need to force-align it
1963 if (type_has_references (klass, ftype))
1964 align = MAX (align, sizeof (gpointer));
1966 min_align = MAX (align, min_align);
1967 field_offsets [i] = real_size;
1969 field_offsets [i] += align - 1;
1970 field_offsets [i] &= ~(align - 1);
1972 /*TypeBuilders produce all sort of weird things*/
1973 g_assert (image_is_dynamic (klass->image) || field_offsets [i] > 0);
1974 real_size = field_offsets [i] + size;
1977 /* Make SIMD types as big as a SIMD register since they can be stored into using simd stores */
1978 if (klass->simd_type)
1979 real_size = MAX (real_size, sizeof (MonoObject) + 16);
1980 instance_size = MAX (real_size, instance_size);
1982 if (instance_size & (min_align - 1)) {
1983 instance_size += min_align - 1;
1984 instance_size &= ~(min_align - 1);
1988 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
1992 for (i = 0; i < top; i++) {
1997 field = &klass->fields [i];
2000 * There must be info about all the fields in a type if it
2001 * uses explicit layout.
2003 if (mono_field_is_deleted (field))
2005 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2008 size = mono_type_size (field->type, &align);
2009 align = packing_size ? MIN (packing_size, align): align;
2010 min_align = MAX (align, min_align);
2013 /* Already set by typebuilder_setup_fields () */
2014 field_offsets [i] = field->offset + sizeof (MonoObject);
2016 int idx = first_field_idx + i;
2018 mono_metadata_field_info (klass->image, idx, &offset, NULL, NULL);
2019 field_offsets [i] = offset + sizeof (MonoObject);
2021 ftype = mono_type_get_underlying_type (field->type);
2022 ftype = mono_type_get_basic_type_from_generic (ftype);
2023 if (type_has_references (klass, ftype)) {
2024 if (field_offsets [i] % sizeof (gpointer)) {
2025 mono_class_set_type_load_failure (klass, "Reference typed field '%s' has explicit offset that is not pointer-size aligned.", field->name);
2032 real_size = MAX (real_size, size + field_offsets [i]);
2035 if (klass->has_references) {
2036 ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
2038 /* Check for overlapping reference and non-reference fields */
2039 for (i = 0; i < top; i++) {
2042 field = &klass->fields [i];
2044 if (mono_field_is_deleted (field))
2046 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2048 ftype = mono_type_get_underlying_type (field->type);
2049 if (MONO_TYPE_IS_REFERENCE (ftype))
2050 ref_bitmap [field_offsets [i] / sizeof (gpointer)] = 1;
2052 for (i = 0; i < top; i++) {
2053 field = &klass->fields [i];
2055 if (mono_field_is_deleted (field))
2057 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2060 // FIXME: Too much code does this
2062 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field_offsets [i] / sizeof (gpointer)]) {
2063 mono_class_set_type_load_failure (klass, "Could not load type '%s' because it contains an object field at offset %d that is incorrectly aligned or overlapped by a non-object field.", klass->name, field_offsets [i]);
2067 g_free (ref_bitmap);
2070 instance_size = MAX (real_size, instance_size);
2071 if (instance_size & (min_align - 1)) {
2072 instance_size += min_align - 1;
2073 instance_size &= ~(min_align - 1);
2079 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2081 * This leads to all kinds of problems with nested structs, so only
2082 * enable it when a MONO_DEBUG property is set.
2084 * For small structs, set min_align to at least the struct size to improve
2085 * performance, and since the JIT memset/memcpy code assumes this and generates
2086 * unaligned accesses otherwise. See #78990 for a testcase.
2088 if (mono_align_small_structs && top) {
2089 if (instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2090 min_align = MAX (min_align, instance_size - sizeof (MonoObject));
2094 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR)
2095 instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
2096 else if (klass->byval_arg.type == MONO_TYPE_PTR)
2097 instance_size = sizeof (MonoObject) + sizeof (gpointer);
2099 /* Publish the data */
2100 mono_loader_lock ();
2101 if (klass->instance_size && !klass->image->dynamic) {
2102 /* Might be already set using cached info */
2103 if (klass->instance_size != instance_size) {
2104 /* Emit info to help debugging */
2105 g_print ("%s\n", mono_class_full_name (klass));
2106 g_print ("%d %d %d %d\n", klass->instance_size, instance_size, klass->blittable, blittable);
2107 g_print ("%d %d %d %d\n", klass->has_references, has_references, klass->packing_size, packing_size);
2108 g_print ("%d %d\n", klass->min_align, min_align);
2109 for (i = 0; i < top; ++i) {
2110 field = &klass->fields [i];
2111 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
2112 printf (" %s %d %d %d\n", klass->fields [i].name, klass->fields [i].offset, field_offsets [i], fields_has_references [i]);
2115 g_assert (klass->instance_size == instance_size);
2117 klass->instance_size = instance_size;
2119 klass->blittable = blittable;
2120 klass->has_references = has_references;
2121 klass->packing_size = packing_size;
2122 klass->min_align = min_align;
2123 for (i = 0; i < top; ++i) {
2124 field = &klass->fields [i];
2125 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
2126 klass->fields [i].offset = field_offsets [i];
2129 mono_memory_barrier ();
2130 klass->size_inited = 1;
2131 mono_loader_unlock ();
2134 * Compute static field layout and size
2135 * Static fields can reference the class itself, so this has to be
2136 * done after instance_size etc. are initialized.
2139 for (i = 0; i < top; i++) {
2143 field = &klass->fields [i];
2145 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2147 if (mono_field_is_deleted (field))
2150 if (mono_type_has_exceptions (field->type)) {
2151 mono_class_set_type_load_failure (klass, "Field '%s' has an invalid type.", field->name);
2155 has_static_fields = TRUE;
2157 size = mono_type_size (field->type, &align);
2158 field_offsets [i] = class_size;
2159 /*align is always non-zero here*/
2160 field_offsets [i] += align - 1;
2161 field_offsets [i] &= ~(align - 1);
2162 class_size = field_offsets [i] + size;
2165 if (has_static_fields && class_size == 0)
2166 /* Simplify code which depends on class_size != 0 if the class has static fields */
2169 /* Compute klass->has_static_refs */
2170 has_static_refs = FALSE;
2171 for (i = 0; i < top; i++) {
2174 field = &klass->fields [i];
2176 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
2177 ftype = mono_type_get_underlying_type (field->type);
2178 ftype = mono_type_get_basic_type_from_generic (ftype);
2179 if (type_has_references (klass, ftype))
2180 has_static_refs = TRUE;
2184 /*valuetypes can't be neither bigger than 1Mb or empty. */
2185 if (klass->valuetype && (klass->instance_size <= 0 || klass->instance_size > (0x100000 + sizeof (MonoObject))))
2186 mono_class_set_type_load_failure (klass, "Value type instance size (%d) cannot be zero, negative, or bigger than 1Mb", klass->instance_size);
2188 /* Publish the data */
2189 mono_loader_lock ();
2191 klass->sizes.class_size = class_size;
2192 klass->has_static_refs = has_static_refs;
2193 for (i = 0; i < top; ++i) {
2194 field = &klass->fields [i];
2196 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2197 field->offset = field_offsets [i];
2200 mono_memory_barrier ();
2201 klass->fields_inited = 1;
2202 mono_loader_unlock ();
2204 g_free (field_offsets);
2205 g_free (fields_has_references);
2209 create_array_method (MonoClass *klass, const char *name, MonoMethodSignature *sig)
2213 method = (MonoMethod *) mono_image_alloc0 (klass->image, sizeof (MonoMethodPInvoke));
2214 method->klass = klass;
2215 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2216 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2217 method->signature = sig;
2218 method->name = name;
2221 if (name [0] == '.') {
2222 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2224 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2230 * mono_class_setup_methods:
2233 * Initializes the 'methods' array in CLASS.
2234 * Calling this method should be avoided if possible since it allocates a lot
2235 * of long-living MonoMethod structures.
2236 * Methods belonging to an interface are assigned a sequential slot starting
2239 * On failure this function sets klass->has_failure and stores a MonoErrorBoxed with details
2242 mono_class_setup_methods (MonoClass *klass)
2245 MonoMethod **methods;
2250 if (mono_class_is_ginst (klass)) {
2252 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2254 mono_class_init (gklass);
2255 if (!mono_class_has_failure (gklass))
2256 mono_class_setup_methods (gklass);
2257 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2260 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2261 count = mono_class_get_method_count (gklass);
2262 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * (count + 1));
2264 for (i = 0; i < count; i++) {
2265 methods [i] = mono_class_inflate_generic_method_full_checked (
2266 gklass->methods [i], klass, mono_class_get_context (klass), &error);
2267 if (!mono_error_ok (&error)) {
2268 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2269 mono_class_set_type_load_failure (klass, "Could not inflate method %s due to %s", method, mono_error_get_message (&error));
2272 mono_error_cleanup (&error);
2276 } else if (klass->rank) {
2278 MonoMethod *amethod;
2279 MonoMethodSignature *sig;
2280 int count_generic = 0, first_generic = 0;
2282 gboolean jagged_ctor = FALSE;
2284 count = 3 + (klass->rank > 1? 2: 1);
2286 mono_class_setup_interfaces (klass, &error);
2287 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2289 if (klass->rank == 1 && klass->element_class->rank) {
2294 if (klass->interface_count) {
2295 count_generic = generic_array_methods (klass);
2296 first_generic = count;
2297 count += klass->interface_count * count_generic;
2300 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * count);
2302 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2303 sig->ret = &mono_defaults.void_class->byval_arg;
2304 sig->pinvoke = TRUE;
2305 sig->hasthis = TRUE;
2306 for (i = 0; i < klass->rank; ++i)
2307 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2309 amethod = create_array_method (klass, ".ctor", sig);
2310 methods [method_num++] = amethod;
2311 if (klass->rank > 1) {
2312 sig = mono_metadata_signature_alloc (klass->image, klass->rank * 2);
2313 sig->ret = &mono_defaults.void_class->byval_arg;
2314 sig->pinvoke = TRUE;
2315 sig->hasthis = TRUE;
2316 for (i = 0; i < klass->rank * 2; ++i)
2317 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2319 amethod = create_array_method (klass, ".ctor", sig);
2320 methods [method_num++] = amethod;
2324 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2325 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2326 sig->ret = &mono_defaults.void_class->byval_arg;
2327 sig->pinvoke = TRUE;
2328 sig->hasthis = TRUE;
2329 for (i = 0; i < klass->rank + 1; ++i)
2330 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2331 amethod = create_array_method (klass, ".ctor", sig);
2332 methods [method_num++] = amethod;
2335 /* element Get (idx11, [idx2, ...]) */
2336 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2337 sig->ret = &klass->element_class->byval_arg;
2338 sig->pinvoke = TRUE;
2339 sig->hasthis = TRUE;
2340 for (i = 0; i < klass->rank; ++i)
2341 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2342 amethod = create_array_method (klass, "Get", sig);
2343 methods [method_num++] = amethod;
2344 /* element& Address (idx11, [idx2, ...]) */
2345 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2346 sig->ret = &klass->element_class->this_arg;
2347 sig->pinvoke = TRUE;
2348 sig->hasthis = TRUE;
2349 for (i = 0; i < klass->rank; ++i)
2350 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2351 amethod = create_array_method (klass, "Address", sig);
2352 methods [method_num++] = amethod;
2353 /* void Set (idx11, [idx2, ...], element) */
2354 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2355 sig->ret = &mono_defaults.void_class->byval_arg;
2356 sig->pinvoke = TRUE;
2357 sig->hasthis = TRUE;
2358 for (i = 0; i < klass->rank; ++i)
2359 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2360 sig->params [i] = &klass->element_class->byval_arg;
2361 amethod = create_array_method (klass, "Set", sig);
2362 methods [method_num++] = amethod;
2364 for (i = 0; i < klass->interface_count; i++)
2365 setup_generic_array_ifaces (klass, klass->interfaces [i], methods, first_generic + i * count_generic);
2366 } else if (mono_class_has_static_metadata (klass)) {
2368 int first_idx = mono_class_get_first_method_idx (klass);
2370 count = mono_class_get_method_count (klass);
2371 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * count);
2372 for (i = 0; i < count; ++i) {
2373 int idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_METHOD, first_idx + i + 1);
2374 methods [i] = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | idx, klass, NULL, &error);
2376 mono_class_set_type_load_failure (klass, "Could not load method %d due to %s", i, mono_error_get_message (&error));
2377 mono_error_cleanup (&error);
2381 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * 1);
2385 if (MONO_CLASS_IS_INTERFACE (klass)) {
2387 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2388 for (i = 0; i < count; ++i) {
2389 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2390 methods [i]->slot = slot++;
2394 mono_image_lock (klass->image);
2396 if (!klass->methods) {
2397 mono_class_set_method_count (klass, count);
2399 /* Needed because of the double-checking locking pattern */
2400 mono_memory_barrier ();
2402 klass->methods = methods;
2405 mono_image_unlock (klass->image);
2409 * mono_class_get_method_by_index:
2411 * Returns klass->methods [index], initializing klass->methods if neccesary.
2413 * LOCKING: Acquires the loader lock.
2416 mono_class_get_method_by_index (MonoClass *klass, int index)
2420 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
2421 /* Avoid calling setup_methods () if possible */
2422 if (gklass && !klass->methods) {
2425 m = mono_class_inflate_generic_method_full_checked (
2426 gklass->container_class->methods [index], klass, mono_class_get_context (klass), &error);
2427 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2429 * If setup_methods () is called later for this class, no duplicates are created,
2430 * since inflate_generic_method guarantees that only one instance of a method
2431 * is created for each context.
2434 mono_class_setup_methods (klass);
2435 g_assert (m == klass->methods [index]);
2439 mono_class_setup_methods (klass);
2440 if (mono_class_has_failure (klass)) /*FIXME do proper error handling*/
2442 g_assert (index >= 0 && index < mono_class_get_method_count (klass));
2443 return klass->methods [index];
2448 * mono_class_get_inflated_method:
2450 * Given an inflated class CLASS and a method METHOD which should be a method of
2451 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2454 mono_class_get_inflated_method (MonoClass *klass, MonoMethod *method)
2456 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2459 g_assert (method->klass == gklass);
2461 mono_class_setup_methods (gklass);
2462 g_assert (!mono_class_has_failure (gklass)); /*FIXME do proper error handling*/
2464 mcount = mono_class_get_method_count (gklass);
2465 for (i = 0; i < mcount; ++i) {
2466 if (gklass->methods [i] == method) {
2467 if (klass->methods) {
2468 return klass->methods [i];
2471 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], klass, mono_class_get_context (klass), &error);
2472 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2482 * mono_class_get_vtable_entry:
2484 * Returns klass->vtable [offset], computing it if neccesary. Returns NULL on failure.
2485 * LOCKING: Acquires the loader lock.
2488 mono_class_get_vtable_entry (MonoClass *klass, int offset)
2492 if (klass->rank == 1) {
2494 * szarrays do not overwrite any methods of Array, so we can avoid
2495 * initializing their vtables in some cases.
2497 mono_class_setup_vtable (klass->parent);
2498 if (offset < klass->parent->vtable_size)
2499 return klass->parent->vtable [offset];
2502 if (mono_class_is_ginst (klass)) {
2504 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2505 mono_class_setup_vtable (gklass);
2506 m = gklass->vtable [offset];
2508 m = mono_class_inflate_generic_method_full_checked (m, klass, mono_class_get_context (klass), &error);
2509 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2511 mono_class_setup_vtable (klass);
2512 if (mono_class_has_failure (klass))
2514 m = klass->vtable [offset];
2521 * mono_class_get_vtable_size:
2523 * Return the vtable size for KLASS.
2526 mono_class_get_vtable_size (MonoClass *klass)
2528 mono_class_setup_vtable (klass);
2530 return klass->vtable_size;
2534 * mono_class_setup_properties:
2536 * Initialize klass->ext.property and klass->ext.properties.
2538 * This method can fail the class.
2541 mono_class_setup_properties (MonoClass *klass)
2543 guint startm, endm, i, j;
2544 guint32 cols [MONO_PROPERTY_SIZE];
2545 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2546 MonoProperty *properties;
2549 MonoClassPropertyInfo *info;
2551 info = mono_class_get_property_info (klass);
2555 if (mono_class_is_ginst (klass)) {
2556 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2558 mono_class_init (gklass);
2559 mono_class_setup_properties (gklass);
2560 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2563 MonoClassPropertyInfo *ginfo = mono_class_get_property_info (gklass);
2564 properties = mono_class_new0 (klass, MonoProperty, ginfo->count + 1);
2566 for (i = 0; i < ginfo->count; i++) {
2568 MonoProperty *prop = &properties [i];
2570 *prop = ginfo->properties [i];
2573 prop->get = mono_class_inflate_generic_method_full_checked (
2574 prop->get, klass, mono_class_get_context (klass), &error);
2576 prop->set = mono_class_inflate_generic_method_full_checked (
2577 prop->set, klass, mono_class_get_context (klass), &error);
2579 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2580 prop->parent = klass;
2583 first = ginfo->first;
2584 count = ginfo->count;
2586 first = mono_metadata_properties_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2587 count = last - first;
2590 mono_class_setup_methods (klass);
2591 if (mono_class_has_failure (klass))
2595 properties = (MonoProperty *)mono_class_alloc0 (klass, sizeof (MonoProperty) * count);
2596 for (i = first; i < last; ++i) {
2597 mono_metadata_decode_table_row (klass->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2598 properties [i - first].parent = klass;
2599 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2600 properties [i - first].name = mono_metadata_string_heap (klass->image, cols [MONO_PROPERTY_NAME]);
2602 startm = mono_metadata_methods_from_property (klass->image, i, &endm);
2603 int first_idx = mono_class_get_first_method_idx (klass);
2604 for (j = startm; j < endm; ++j) {
2607 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2609 if (klass->image->uncompressed_metadata) {
2611 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2612 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2613 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2615 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - first_idx];
2618 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2619 case METHOD_SEMANTIC_SETTER:
2620 properties [i - first].set = method;
2622 case METHOD_SEMANTIC_GETTER:
2623 properties [i - first].get = method;
2632 info = mono_class_alloc0 (klass, sizeof (MonoClassPropertyInfo));
2633 info->first = first;
2634 info->count = count;
2635 info->properties = properties;
2636 mono_memory_barrier ();
2638 /* This might leak 'info' which was allocated from the image mempool */
2639 mono_class_set_property_info (klass, info);
2643 inflate_method_listz (MonoMethod **methods, MonoClass *klass, MonoGenericContext *context)
2645 MonoMethod **om, **retval;
2648 for (om = methods, count = 0; *om; ++om, ++count)
2651 retval = g_new0 (MonoMethod*, count + 1);
2653 for (om = methods, count = 0; *om; ++om, ++count) {
2655 retval [count] = mono_class_inflate_generic_method_full_checked (*om, klass, context, &error);
2656 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2662 /*This method can fail the class.*/
2664 mono_class_setup_events (MonoClass *klass)
2667 guint startm, endm, i, j;
2668 guint32 cols [MONO_EVENT_SIZE];
2669 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2673 MonoClassEventInfo *info = mono_class_get_event_info (klass);
2677 if (mono_class_is_ginst (klass)) {
2678 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2679 MonoGenericContext *context = NULL;
2681 mono_class_setup_events (gklass);
2682 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2685 MonoClassEventInfo *ginfo = mono_class_get_event_info (gklass);
2686 first = ginfo->first;
2687 count = ginfo->count;
2689 events = mono_class_new0 (klass, MonoEvent, count);
2692 context = mono_class_get_context (klass);
2694 for (i = 0; i < count; i++) {
2696 MonoEvent *event = &events [i];
2697 MonoEvent *gevent = &ginfo->events [i];
2699 mono_error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2701 event->parent = klass;
2702 event->name = gevent->name;
2703 event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, klass, context, &error) : NULL;
2704 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2705 event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, klass, context, &error) : NULL;
2706 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2707 event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, klass, context, &error) : NULL;
2708 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2710 #ifndef MONO_SMALL_CONFIG
2711 event->other = gevent->other ? inflate_method_listz (gevent->other, klass, context) : NULL;
2713 event->attrs = gevent->attrs;
2716 first = mono_metadata_events_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2717 count = last - first;
2720 mono_class_setup_methods (klass);
2721 if (mono_class_has_failure (klass)) {
2726 events = (MonoEvent *)mono_class_alloc0 (klass, sizeof (MonoEvent) * count);
2727 for (i = first; i < last; ++i) {
2728 MonoEvent *event = &events [i - first];
2730 mono_metadata_decode_table_row (klass->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2731 event->parent = klass;
2732 event->attrs = cols [MONO_EVENT_FLAGS];
2733 event->name = mono_metadata_string_heap (klass->image, cols [MONO_EVENT_NAME]);
2735 startm = mono_metadata_methods_from_event (klass->image, i, &endm);
2736 int first_idx = mono_class_get_first_method_idx (klass);
2737 for (j = startm; j < endm; ++j) {
2740 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2742 if (klass->image->uncompressed_metadata) {
2744 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2745 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2746 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2748 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - first_idx];
2751 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2752 case METHOD_SEMANTIC_ADD_ON:
2753 event->add = method;
2755 case METHOD_SEMANTIC_REMOVE_ON:
2756 event->remove = method;
2758 case METHOD_SEMANTIC_FIRE:
2759 event->raise = method;
2761 case METHOD_SEMANTIC_OTHER: {
2762 #ifndef MONO_SMALL_CONFIG
2765 if (event->other == NULL) {
2766 event->other = g_new0 (MonoMethod*, 2);
2768 while (event->other [n])
2770 event->other = (MonoMethod **)g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2772 event->other [n] = method;
2773 /* NULL terminated */
2774 event->other [n + 1] = NULL;
2785 info = mono_class_alloc0 (klass, sizeof (MonoClassEventInfo));
2786 info->events = events;
2787 info->first = first;
2788 info->count = count;
2790 mono_memory_barrier ();
2792 mono_class_set_event_info (klass, info);
2796 * Global pool of interface IDs, represented as a bitset.
2797 * LOCKING: Protected by the classes lock.
2799 static MonoBitSet *global_interface_bitset = NULL;
2802 * mono_unload_interface_ids:
2803 * @bitset: bit set of interface IDs
2805 * When an image is unloaded, the interface IDs associated with
2806 * the image are put back in the global pool of IDs so the numbers
2810 mono_unload_interface_ids (MonoBitSet *bitset)
2813 mono_bitset_sub (global_interface_bitset, bitset);
2818 mono_unload_interface_id (MonoClass *klass)
2820 if (global_interface_bitset && klass->interface_id) {
2822 mono_bitset_clear (global_interface_bitset, klass->interface_id);
2828 * mono_get_unique_iid:
2831 * Assign a unique integer ID to the interface represented by @class.
2832 * The ID will positive and as small as possible.
2833 * LOCKING: Acquires the classes lock.
2834 * Returns: The new ID.
2837 mono_get_unique_iid (MonoClass *klass)
2841 g_assert (MONO_CLASS_IS_INTERFACE (klass));
2845 if (!global_interface_bitset) {
2846 global_interface_bitset = mono_bitset_new (128, 0);
2849 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2851 int old_size = mono_bitset_size (global_interface_bitset);
2852 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2853 mono_bitset_free (global_interface_bitset);
2854 global_interface_bitset = new_set;
2857 mono_bitset_set (global_interface_bitset, iid);
2858 /* set the bit also in the per-image set */
2859 if (!mono_class_is_ginst (klass)) {
2860 if (klass->image->interface_bitset) {
2861 if (iid >= mono_bitset_size (klass->image->interface_bitset)) {
2862 MonoBitSet *new_set = mono_bitset_clone (klass->image->interface_bitset, iid + 1);
2863 mono_bitset_free (klass->image->interface_bitset);
2864 klass->image->interface_bitset = new_set;
2867 klass->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2869 mono_bitset_set (klass->image->interface_bitset, iid);
2874 #ifndef MONO_SMALL_CONFIG
2875 if (mono_print_vtable) {
2877 char *type_name = mono_type_full_name (&klass->byval_arg);
2878 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
2879 if (gklass && !gklass->context.class_inst->is_open) {
2880 generic_id = gklass->context.class_inst->id;
2881 g_assert (generic_id != 0);
2885 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, klass->image->name, type_name, generic_id);
2890 /* I've confirmed iids safe past 16 bits, however bitset code uses a signed int while testing.
2891 * Once this changes, it should be safe for us to allow 2^32-1 interfaces, until then 2^31-2 is the max. */
2892 g_assert (iid < INT_MAX);
2897 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, GHashTable **ifaces, MonoError *error)
2902 mono_class_setup_interfaces (klass, error);
2903 return_if_nok (error);
2905 for (i = 0; i < klass->interface_count; i++) {
2906 ic = klass->interfaces [i];
2909 *res = g_ptr_array_new ();
2910 if (*ifaces == NULL)
2911 *ifaces = g_hash_table_new (NULL, NULL);
2912 if (g_hash_table_lookup (*ifaces, ic))
2914 g_ptr_array_add (*res, ic);
2915 g_hash_table_insert (*ifaces, ic, ic);
2916 mono_class_init (ic);
2917 if (mono_class_has_failure (ic)) {
2918 mono_error_set_type_load_class (error, ic, "Error Loading class");
2922 collect_implemented_interfaces_aux (ic, res, ifaces, error);
2923 return_if_nok (error);
2928 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2930 GPtrArray *res = NULL;
2931 GHashTable *ifaces = NULL;
2933 collect_implemented_interfaces_aux (klass, &res, &ifaces, error);
2935 g_hash_table_destroy (ifaces);
2936 if (!mono_error_ok (error)) {
2938 g_ptr_array_free (res, TRUE);
2945 compare_interface_ids (const void *p_key, const void *p_element)
2947 const MonoClass *key = (const MonoClass *)p_key;
2948 const MonoClass *element = *(const MonoClass **)p_element;
2950 return (key->interface_id - element->interface_id);
2953 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2955 mono_class_interface_offset (MonoClass *klass, MonoClass *itf)
2957 MonoClass **result = (MonoClass **)mono_binary_search (
2959 klass->interfaces_packed,
2960 klass->interface_offsets_count,
2961 sizeof (MonoClass *),
2962 compare_interface_ids);
2964 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2971 * mono_class_interface_offset_with_variance:
2973 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2974 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2976 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2978 * FIXME figure out MS disambiguation rules and fix this function.
2981 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match)
2983 int i = mono_class_interface_offset (klass, itf);
2984 *non_exact_match = FALSE;
2988 if (itf->is_array_special_interface && klass->rank < 2) {
2989 MonoClass *gtd = mono_class_get_generic_type_definition (itf);
2991 for (i = 0; i < klass->interface_offsets_count; i++) {
2992 // printf ("\t%s\n", mono_type_get_full_name (klass->interfaces_packed [i]));
2993 if (mono_class_get_generic_type_definition (klass->interfaces_packed [i]) == gtd) {
2994 *non_exact_match = TRUE;
2995 return klass->interface_offsets_packed [i];
3000 if (!mono_class_has_variant_generic_params (itf))
3003 for (i = 0; i < klass->interface_offsets_count; i++) {
3004 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
3005 *non_exact_match = TRUE;
3006 return klass->interface_offsets_packed [i];
3014 print_implemented_interfaces (MonoClass *klass)
3018 GPtrArray *ifaces = NULL;
3020 int ancestor_level = 0;
3022 name = mono_type_get_full_name (klass);
3023 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
3026 for (i = 0; i < klass->interface_offsets_count; i++)
3027 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3028 klass->interfaces_packed [i]->interface_id,
3029 klass->interface_offsets_packed [i],
3030 mono_class_get_method_count (klass->interfaces_packed [i]),
3031 klass->interfaces_packed [i]->name_space,
3032 klass->interfaces_packed [i]->name );
3033 printf ("Interface flags: ");
3034 for (i = 0; i <= klass->max_interface_id; i++)
3035 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
3036 printf ("(%d,T)", i);
3038 printf ("(%d,F)", i);
3040 printf ("Dump interface flags:");
3041 #ifdef COMPRESSED_INTERFACE_BITMAP
3043 const uint8_t* p = klass->interface_bitmap;
3044 i = klass->max_interface_id;
3046 printf (" %d x 00 %02X", p [0], p [1]);
3052 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
3053 printf (" %02X", klass->interface_bitmap [i]);
3056 while (klass != NULL) {
3057 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
3058 ifaces = mono_class_get_implemented_interfaces (klass, &error);
3059 if (!mono_error_ok (&error)) {
3060 printf (" Type failed due to %s\n", mono_error_get_message (&error));
3061 mono_error_cleanup (&error);
3062 } else if (ifaces) {
3063 for (i = 0; i < ifaces->len; i++) {
3064 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3065 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
3066 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3068 mono_class_interface_offset (klass, ic),
3069 mono_class_get_method_count (ic),
3073 g_ptr_array_free (ifaces, TRUE);
3076 klass = klass->parent;
3081 * Return the number of virtual methods.
3082 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3083 * Return -1 on failure.
3084 * FIXME It would be nice if this information could be cached somewhere.
3087 count_virtual_methods (MonoClass *klass)
3089 int i, mcount, vcount = 0;
3091 klass = mono_class_get_generic_type_definition (klass); /*We can find this information by looking at the GTD*/
3093 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
3094 mono_class_setup_methods (klass);
3095 if (mono_class_has_failure (klass))
3098 mcount = mono_class_get_method_count (klass);
3099 for (i = 0; i < mcount; ++i) {
3100 flags = klass->methods [i]->flags;
3101 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3105 int first_idx = mono_class_get_first_method_idx (klass);
3106 mcount = mono_class_get_method_count (klass);
3107 for (i = 0; i < mcount; ++i) {
3108 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
3110 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3118 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3126 m = (l + num_ifaces) / 2;
3127 if (interfaces_full [m] == ic)
3129 if (l == num_ifaces)
3131 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3140 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3142 int i = find_interface (num_ifaces, interfaces_full, ic);
3146 interface_offsets_full [i] = offset;
3149 for (i = 0; i < num_ifaces; ++i) {
3150 if (interfaces_full [i]) {
3152 if (interfaces_full [i]->interface_id < ic->interface_id)
3155 while (end < num_ifaces && interfaces_full [end]) end++;
3156 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3157 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3159 interfaces_full [i] = ic;
3160 interface_offsets_full [i] = offset;
3166 #ifdef COMPRESSED_INTERFACE_BITMAP
3169 * Compressed interface bitmap design.
3171 * Interface bitmaps take a large amount of memory, because their size is
3172 * linear with the maximum interface id assigned in the process (each interface
3173 * is assigned a unique id as it is loaded). The number of interface classes
3174 * is high because of the many implicit interfaces implemented by arrays (we'll
3175 * need to lazy-load them in the future).
3176 * Most classes implement a very small number of interfaces, so the bitmap is
3177 * sparse. This bitmap needs to be checked by interface casts, so access to the
3178 * needed bit must be fast and doable with few jit instructions.
3180 * The current compression format is as follows:
3181 * *) it is a sequence of one or more two-byte elements
3182 * *) the first byte in the element is the count of empty bitmap bytes
3183 * at the current bitmap position
3184 * *) the second byte in the element is an actual bitmap byte at the current
3187 * As an example, the following compressed bitmap bytes:
3188 * 0x07 0x01 0x00 0x7
3189 * correspond to the following bitmap:
3190 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3192 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3193 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3194 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3198 * mono_compress_bitmap:
3199 * @dest: destination buffer
3200 * @bitmap: bitmap buffer
3201 * @size: size of @bitmap in bytes
3203 * This is a mono internal function.
3204 * The @bitmap data is compressed into a format that is small but
3205 * still searchable in few instructions by the JIT and runtime.
3206 * The compressed data is stored in the buffer pointed to by the
3207 * @dest array. Passing a #NULL value for @dest allows to just compute
3208 * the size of the buffer.
3209 * This compression algorithm assumes the bits set in the bitmap are
3210 * few and far between, like in interface bitmaps.
3211 * Returns: The size of the compressed bitmap in bytes.
3214 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3218 const uint8_t *end = bitmap + size;
3219 while (bitmap < end) {
3220 if (*bitmap || numz == 255) {
3244 * mono_class_interface_match:
3245 * @bitmap: a compressed bitmap buffer
3246 * @id: the index to check in the bitmap
3248 * This is a mono internal function.
3249 * Checks if a bit is set in a compressed interface bitmap. @id must
3250 * be already checked for being smaller than the maximum id encoded in the
3253 * Returns: A non-zero value if bit @id is set in the bitmap @bitmap,
3257 mono_class_interface_match (const uint8_t *bitmap, int id)
3260 id -= bitmap [0] * 8;
3264 return bitmap [1] & (1 << id);
3273 * Return -1 on failure and set klass->has_failure and store a MonoErrorBoxed with the details.
3274 * LOCKING: Acquires the loader lock.
3277 setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite)
3281 int i, j, num_ifaces;
3283 MonoClass **interfaces_full = NULL;
3284 int *interface_offsets_full = NULL;
3286 GPtrArray **ifaces_array = NULL;
3287 int interface_offsets_count;
3289 mono_loader_lock ();
3291 mono_class_setup_supertypes (klass);
3293 /* compute maximum number of slots and maximum interface id */
3295 num_ifaces = 0; /* this can include duplicated ones */
3296 ifaces_array = g_new0 (GPtrArray *, klass->idepth);
3297 for (j = 0; j < klass->idepth; j++) {
3298 k = klass->supertypes [j];
3300 num_ifaces += k->interface_count;
3301 for (i = 0; i < k->interface_count; i++) {
3302 ic = k->interfaces [i];
3304 mono_class_init (ic);
3306 if (max_iid < ic->interface_id)
3307 max_iid = ic->interface_id;
3309 ifaces = mono_class_get_implemented_interfaces (k, &error);
3310 if (!mono_error_ok (&error)) {
3311 char *name = mono_type_get_full_name (k);
3312 mono_class_set_type_load_failure (klass, "Error getting the interfaces of %s due to %s", name, mono_error_get_message (&error));
3314 mono_error_cleanup (&error);
3319 num_ifaces += ifaces->len;
3320 for (i = 0; i < ifaces->len; ++i) {
3321 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3322 if (max_iid < ic->interface_id)
3323 max_iid = ic->interface_id;
3325 ifaces_array [j] = ifaces;
3329 if (MONO_CLASS_IS_INTERFACE (klass)) {
3331 if (max_iid < klass->interface_id)
3332 max_iid = klass->interface_id;
3335 /* compute vtable offset for interfaces */
3336 interfaces_full = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3337 interface_offsets_full = (int *)g_malloc (sizeof (int) * num_ifaces);
3339 for (i = 0; i < num_ifaces; i++)
3340 interface_offsets_full [i] = -1;
3342 /* skip the current class */
3343 for (j = 0; j < klass->idepth - 1; j++) {
3344 k = klass->supertypes [j];
3345 ifaces = ifaces_array [j];
3348 for (i = 0; i < ifaces->len; ++i) {
3350 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3352 /*Force the sharing of interface offsets between parent and subtypes.*/
3353 io = mono_class_interface_offset (k, ic);
3355 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3360 g_assert (klass == klass->supertypes [klass->idepth - 1]);
3361 ifaces = ifaces_array [klass->idepth - 1];
3363 for (i = 0; i < ifaces->len; ++i) {
3365 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3366 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3368 count = count_virtual_methods (ic);
3370 char *name = mono_type_get_full_name (ic);
3371 mono_class_set_type_load_failure (klass, "Error calculating interface offset of %s", name);
3380 if (MONO_CLASS_IS_INTERFACE (klass))
3381 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, klass, cur_slot, TRUE);
3383 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3384 if (interface_offsets_full [i] != -1)
3385 interface_offsets_count ++;
3388 /* Publish the data */
3389 klass->max_interface_id = max_iid;
3391 * We might get called multiple times:
3392 * - mono_class_init ()
3393 * - mono_class_setup_vtable ().
3394 * - mono_class_setup_interface_offsets ().
3395 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3396 * means we have to overwrite those when called from other places (#4440).
3398 if (klass->interfaces_packed) {
3400 g_assert (klass->interface_offsets_count == interface_offsets_count);
3404 klass->interface_offsets_count = interface_offsets_count;
3405 klass->interfaces_packed = (MonoClass **)mono_class_alloc (klass, sizeof (MonoClass*) * interface_offsets_count);
3406 klass->interface_offsets_packed = (guint16 *)mono_class_alloc (klass, sizeof (guint16) * interface_offsets_count);
3407 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3408 #ifdef COMPRESSED_INTERFACE_BITMAP
3409 bitmap = g_malloc0 (bsize);
3411 bitmap = (uint8_t *)mono_class_alloc0 (klass, bsize);
3413 for (i = 0; i < interface_offsets_count; i++) {
3414 guint32 id = interfaces_full [i]->interface_id;
3415 bitmap [id >> 3] |= (1 << (id & 7));
3416 klass->interfaces_packed [i] = interfaces_full [i];
3417 klass->interface_offsets_packed [i] = interface_offsets_full [i];
3419 #ifdef COMPRESSED_INTERFACE_BITMAP
3420 i = mono_compress_bitmap (NULL, bitmap, bsize);
3421 klass->interface_bitmap = mono_class_alloc0 (klass, i);
3422 mono_compress_bitmap (klass->interface_bitmap, bitmap, bsize);
3425 klass->interface_bitmap = bitmap;
3429 mono_loader_unlock ();
3431 g_free (interfaces_full);
3432 g_free (interface_offsets_full);
3433 for (i = 0; i < klass->idepth; i++) {
3434 ifaces = ifaces_array [i];
3436 g_ptr_array_free (ifaces, TRUE);
3438 g_free (ifaces_array);
3440 //printf ("JUST DONE: ");
3441 //print_implemented_interfaces (klass);
3447 * Setup interface offsets for interfaces.
3449 * - klass->max_interface_id
3450 * - klass->interface_offsets_count
3451 * - klass->interfaces_packed
3452 * - klass->interface_offsets_packed
3453 * - klass->interface_bitmap
3455 * This function can fail @class.
3458 mono_class_setup_interface_offsets (MonoClass *klass)
3460 setup_interface_offsets (klass, 0, FALSE);
3463 /*Checks if @klass has @parent as one of it's parents type gtd
3467 * Bar<T> : Foo<Bar<Bar<T>>>
3471 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3473 klass = mono_class_get_generic_type_definition (klass);
3474 parent = mono_class_get_generic_type_definition (parent);
3475 mono_class_setup_supertypes (klass);
3476 mono_class_setup_supertypes (parent);
3478 return klass->idepth >= parent->idepth &&
3479 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3483 mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup)
3485 MonoGenericInst *ginst;
3488 if (!mono_class_is_ginst (klass)) {
3489 mono_class_setup_vtable_full (klass, in_setup);
3490 return !mono_class_has_failure (klass);
3493 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup);
3494 if (mono_class_set_type_load_failure_causedby_class (klass, mono_class_get_generic_class (klass)->container_class, "Failed to load generic definition vtable"))
3497 ginst = mono_class_get_generic_class (klass)->context.class_inst;
3498 for (i = 0; i < ginst->type_argc; ++i) {
3500 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3502 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3503 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3504 if (mono_class_has_gtd_parent (klass, arg) || mono_class_has_gtd_parent (arg, klass))
3506 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3507 mono_class_set_type_load_failure (klass, "Failed to load generic parameter %d", i);
3515 * mono_class_setup_vtable:
3517 * Creates the generic vtable of CLASS.
3518 * Initializes the following fields in MonoClass:
3521 * Plus all the fields initialized by setup_interface_offsets ().
3522 * If there is an error during vtable construction, klass->has_failure
3523 * is set and details are stored in a MonoErrorBoxed.
3525 * LOCKING: Acquires the loader lock.
3528 mono_class_setup_vtable (MonoClass *klass)
3530 mono_class_setup_vtable_full (klass, NULL);
3534 mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
3537 MonoMethod **overrides;
3538 MonoGenericContext *context;
3546 if (MONO_CLASS_IS_INTERFACE (klass)) {
3547 /* This sets method->slot for all methods if this is an interface */
3548 mono_class_setup_methods (klass);
3552 if (mono_class_has_failure (klass))
3555 if (g_list_find (in_setup, klass))
3558 mono_loader_lock ();
3560 if (klass->vtable) {
3561 mono_loader_unlock ();
3565 mono_stats.generic_vtable_count ++;
3566 in_setup = g_list_prepend (in_setup, klass);
3568 if (mono_class_is_ginst (klass)) {
3569 if (!mono_class_check_vtable_constraints (klass, in_setup)) {
3570 mono_loader_unlock ();
3571 g_list_remove (in_setup, klass);
3575 context = mono_class_get_context (klass);
3576 type_token = mono_class_get_generic_class (klass)->container_class->type_token;
3578 context = (MonoGenericContext *) mono_class_try_get_generic_container (klass); //FIXME is this a case of a try?
3579 type_token = klass->type_token;
3582 if (image_is_dynamic (klass->image)) {
3583 /* Generic instances can have zero method overrides without causing any harm.
3584 * This is true since we don't do layout all over again for them, we simply inflate
3585 * the layout of the parent.
3587 mono_reflection_get_dynamic_overrides (klass, &overrides, &onum, &error);
3588 if (!is_ok (&error)) {
3589 mono_loader_unlock ();
3590 g_list_remove (in_setup, klass);
3591 mono_class_set_type_load_failure (klass, "Could not load list of method overrides due to %s", mono_error_get_message (&error));
3592 mono_error_cleanup (&error);
3596 /* The following call fails if there are missing methods in the type */
3597 /* FIXME it's probably a good idea to avoid this for generic instances. */
3598 ok = mono_class_get_overrides_full (klass->image, type_token, &overrides, &onum, context);
3602 mono_class_setup_vtable_general (klass, overrides, onum, in_setup);
3604 mono_class_set_type_load_failure (klass, "Could not load list of method overrides");
3608 mono_loader_unlock ();
3609 g_list_remove (in_setup, klass);
3614 #define DEBUG_INTERFACE_VTABLE_CODE 0
3615 #define TRACE_INTERFACE_VTABLE_CODE 0
3616 #define VERIFY_INTERFACE_VTABLE_CODE 0
3617 #define VTABLE_SELECTOR (1)
3619 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3620 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3621 if (!(VTABLE_SELECTOR)) break; \
3625 #define DEBUG_INTERFACE_VTABLE(stmt)
3628 #if TRACE_INTERFACE_VTABLE_CODE
3629 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3630 if (!(VTABLE_SELECTOR)) break; \
3634 #define TRACE_INTERFACE_VTABLE(stmt)
3637 #if VERIFY_INTERFACE_VTABLE_CODE
3638 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3639 if (!(VTABLE_SELECTOR)) break; \
3643 #define VERIFY_INTERFACE_VTABLE(stmt)
3647 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3649 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3653 GString *res = g_string_new ("");
3655 g_string_append_c (res, '(');
3656 for (i = 0; i < sig->param_count; ++i) {
3658 g_string_append_c (res, ',');
3659 mono_type_get_desc (res, sig->params [i], include_namespace);
3661 g_string_append (res, ")=>");
3662 if (sig->ret != NULL) {
3663 mono_type_get_desc (res, sig->ret, include_namespace);
3665 g_string_append (res, "NULL");
3668 g_string_free (res, FALSE);
3672 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3673 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3674 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3675 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3683 is_wcf_hack_disabled (void)
3685 static gboolean disabled;
3686 static gboolean inited = FALSE;
3688 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3695 check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
3697 MonoMethodSignature *cmsig, *imsig;
3698 if (strcmp (im->name, cm->name) == 0) {
3699 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3700 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3703 if (! slot_is_empty) {
3704 if (require_newslot) {
3705 if (! interface_is_explicitly_implemented_by_class) {
3706 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3709 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3710 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3714 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3717 cmsig = mono_method_signature (cm);
3718 imsig = mono_method_signature (im);
3719 if (!cmsig || !imsig) {
3720 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
3724 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3725 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3726 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3727 TRACE_INTERFACE_VTABLE (printf ("]"));
3730 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3731 if (mono_security_core_clr_enabled ())
3732 mono_security_core_clr_check_override (klass, cm, im);
3734 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
3735 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3736 char *body_name = mono_method_full_name (cm, TRUE);
3737 char *decl_name = mono_method_full_name (im, TRUE);
3738 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
3746 MonoClass *ic = im->klass;
3747 const char *ic_name_space = ic->name_space;
3748 const char *ic_name = ic->name;
3751 if (! require_newslot) {
3752 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
3755 if (cm->klass->rank == 0) {
3756 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
3759 cmsig = mono_method_signature (cm);
3760 imsig = mono_method_signature (im);
3761 if (!cmsig || !imsig) {
3762 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
3766 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3767 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
3768 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3769 TRACE_INTERFACE_VTABLE (printf ("]"));
3772 if (mono_class_get_image (ic) != mono_defaults.corlib) {
3773 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
3776 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
3777 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
3780 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))) {
3781 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
3785 subname = strstr (cm->name, ic_name_space);
3786 if (subname != cm->name) {
3787 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
3790 subname += strlen (ic_name_space);
3791 if (subname [0] != '.') {
3792 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
3796 if (strstr (subname, ic_name) != subname) {
3797 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
3800 subname += strlen (ic_name);
3801 if (subname [0] != '.') {
3802 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
3806 if (strcmp (subname, im->name) != 0) {
3807 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
3811 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
3812 if (mono_security_core_clr_enabled ())
3813 mono_security_core_clr_check_override (klass, cm, im);
3815 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
3816 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3817 char *body_name = mono_method_full_name (cm, TRUE);
3818 char *decl_name = mono_method_full_name (im, TRUE);
3819 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
3829 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3831 foreach_override (gpointer key, gpointer value, gpointer user_data) {
3832 MonoMethod *method = key;
3833 MonoMethod *override = value;
3834 MonoClass *method_class = mono_method_get_class (method);
3835 MonoClass *override_class = mono_method_get_class (override);
3837 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
3838 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
3839 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
3842 print_overrides (GHashTable *override_map, const char *message) {
3844 printf ("Override map \"%s\" START:\n", message);
3845 g_hash_table_foreach (override_map, foreach_override, NULL);
3846 printf ("Override map \"%s\" END.\n", message);
3848 printf ("Override map \"%s\" EMPTY.\n", message);
3852 print_vtable_full (MonoClass *klass, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
3853 char *full_name = mono_type_full_name (&klass->byval_arg);
3857 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
3859 if (print_interfaces) {
3860 print_implemented_interfaces (klass);
3861 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
3864 if (klass->parent) {
3865 parent_size = klass->parent->vtable_size;
3869 for (i = 0; i < size; ++i) {
3870 MonoMethod *cm = vtable [i];
3871 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
3872 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
3874 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
3882 #if VERIFY_INTERFACE_VTABLE_CODE
3884 mono_method_try_get_vtable_index (MonoMethod *method)
3886 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
3887 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
3888 if (imethod->declaring->is_generic)
3889 return imethod->declaring->slot;
3891 return method->slot;
3895 mono_class_verify_vtable (MonoClass *klass)
3898 char *full_name = mono_type_full_name (&klass->byval_arg);
3900 printf ("*** Verifying VTable of class '%s' \n", full_name);
3904 if (!klass->methods)
3907 count = mono_class_method_count (klass);
3908 for (i = 0; i < count; ++i) {
3909 MonoMethod *cm = klass->methods [i];
3912 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
3916 full_name = mono_method_full_name (cm, TRUE);
3918 slot = mono_method_try_get_vtable_index (cm);
3920 if (slot >= klass->vtable_size) {
3921 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, klass->vtable_size);
3925 if (slot >= 0 && klass->vtable [slot] != cm && (klass->vtable [slot])) {
3926 char *other_name = klass->vtable [slot] ? mono_method_full_name (klass->vtable [slot], TRUE) : g_strdup ("[null value]");
3927 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
3928 g_free (other_name);
3931 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
3938 print_unimplemented_interface_method_info (MonoClass *klass, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum)
3941 char *method_signature;
3944 for (index = 0; index < onum; ++index) {
3945 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)", im_slot, overrides [index*2+1]->name,
3946 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
3948 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
3949 type_name = mono_type_full_name (&klass->byval_arg);
3950 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s",
3951 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
3952 g_free (method_signature);
3954 mono_class_setup_methods (klass);
3955 if (mono_class_has_failure (klass)) {
3956 char *name = mono_type_get_full_name (klass);
3957 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods", name);
3961 mcount = mono_class_get_method_count (klass);
3962 for (index = 0; index < mcount; ++index) {
3963 MonoMethod *cm = klass->methods [index];
3964 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
3966 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)", cm->name, method_signature);
3967 g_free (method_signature);
3972 mono_method_get_method_definition (MonoMethod *method)
3974 while (method->is_inflated)
3975 method = ((MonoMethodInflated*)method)->declaring;
3980 verify_class_overrides (MonoClass *klass, MonoMethod **overrides, int onum)
3984 for (i = 0; i < onum; ++i) {
3985 MonoMethod *decl = overrides [i * 2];
3986 MonoMethod *body = overrides [i * 2 + 1];
3988 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (klass)) {
3989 mono_class_set_type_load_failure (klass, "Method belongs to a different class than the declared one");
3993 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
3994 if (body->flags & METHOD_ATTRIBUTE_STATIC)
3995 mono_class_set_type_load_failure (klass, "Method must not be static to override a base type");
3997 mono_class_set_type_load_failure (klass, "Method must be virtual to override a base type");
4001 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4002 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4003 mono_class_set_type_load_failure (klass, "Cannot override a static method in a base type");
4005 mono_class_set_type_load_failure (klass, "Cannot override a non virtual method in a base type");
4009 if (!mono_class_is_assignable_from_slow (decl->klass, klass)) {
4010 mono_class_set_type_load_failure (klass, "Method overrides a class or interface that is not extended or implemented by this type");
4014 body = mono_method_get_method_definition (body);
4015 decl = mono_method_get_method_definition (decl);
4017 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4018 char *body_name = mono_method_full_name (body, TRUE);
4019 char *decl_name = mono_method_full_name (decl, TRUE);
4020 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4030 mono_class_need_stelemref_method (MonoClass *klass)
4032 return klass->rank == 1 && MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg);
4036 * LOCKING: this is supposed to be called with the loader lock held.
4039 mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int onum, GList *in_setup)
4043 MonoMethod **vtable = NULL;
4044 int i, max_vtsize = 0, cur_slot = 0;
4046 GPtrArray *ifaces = NULL;
4047 GHashTable *override_map = NULL;
4049 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4050 int first_non_interface_slot;
4052 GSList *virt_methods = NULL, *l;
4053 int stelemref_slot = 0;
4058 if (overrides && !verify_class_overrides (klass, overrides, onum))
4061 ifaces = mono_class_get_implemented_interfaces (klass, &error);
4062 if (!mono_error_ok (&error)) {
4063 char *name = mono_type_get_full_name (klass);
4064 mono_class_set_type_load_failure (klass, "Could not resolve %s interfaces due to %s", name, mono_error_get_message (&error));
4066 mono_error_cleanup (&error);
4068 } else if (ifaces) {
4069 for (i = 0; i < ifaces->len; i++) {
4070 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
4071 max_vtsize += mono_class_get_method_count (ic);
4073 g_ptr_array_free (ifaces, TRUE);
4077 if (klass->parent) {
4078 mono_class_init (klass->parent);
4079 mono_class_setup_vtable_full (klass->parent, in_setup);
4081 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class failed to load"))
4084 max_vtsize += klass->parent->vtable_size;
4085 cur_slot = klass->parent->vtable_size;
4088 max_vtsize += mono_class_get_method_count (klass);
4090 /*Array have a slot for stelemref*/
4091 if (mono_class_need_stelemref_method (klass)) {
4092 stelemref_slot = cur_slot;
4097 /* printf ("METAINIT %s.%s\n", klass->name_space, klass->name); */
4099 cur_slot = setup_interface_offsets (klass, cur_slot, TRUE);
4100 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4103 max_iid = klass->max_interface_id;
4104 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4106 /* Optimized version for generic instances */
4107 if (mono_class_is_ginst (klass)) {
4109 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4112 mono_class_setup_vtable_full (gklass, in_setup);
4113 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Could not load generic definition"))
4116 tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * gklass->vtable_size);
4117 klass->vtable_size = gklass->vtable_size;
4118 for (i = 0; i < gklass->vtable_size; ++i)
4119 if (gklass->vtable [i]) {
4120 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], klass, mono_class_get_context (klass), &error);
4121 if (!mono_error_ok (&error)) {
4122 mono_class_set_type_load_failure (klass, "Could not inflate method due to %s", mono_error_get_message (&error));
4123 mono_error_cleanup (&error);
4127 tmp [i]->slot = gklass->vtable [i]->slot;
4129 mono_memory_barrier ();
4130 klass->vtable = tmp;
4132 /* Have to set method->slot for abstract virtual methods */
4133 if (klass->methods && gklass->methods) {
4134 int mcount = mono_class_get_method_count (klass);
4135 for (i = 0; i < mcount; ++i)
4136 if (klass->methods [i]->slot == -1)
4137 klass->methods [i]->slot = gklass->methods [i]->slot;
4143 vtable = (MonoMethod **)g_malloc0 (sizeof (gpointer) * max_vtsize);
4145 if (klass->parent && klass->parent->vtable_size) {
4146 MonoClass *parent = klass->parent;
4149 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4151 // Also inherit parent interface vtables, just as a starting point.
4152 // This is needed otherwise bug-77127.exe fails when the property methods
4153 // have different names in the iterface and the class, because for child
4154 // classes the ".override" information is not used anymore.
4155 for (i = 0; i < parent->interface_offsets_count; i++) {
4156 MonoClass *parent_interface = parent->interfaces_packed [i];
4157 int interface_offset = mono_class_interface_offset (klass, parent_interface);
4158 /*FIXME this is now dead code as this condition will never hold true.
4159 Since interface offsets are inherited then the offset of an interface implemented
4160 by a parent will never be the out of it's vtable boundary.
4162 if (interface_offset >= parent->vtable_size) {
4163 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4166 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4167 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4168 int mcount = mono_class_get_method_count (parent_interface);
4169 for (j = 0; j < mcount && !mono_class_has_failure (klass); j++) {
4170 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4171 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4172 parent_interface_offset + j, parent_interface_offset, j,
4173 interface_offset + j, interface_offset, j));
4180 /*Array have a slot for stelemref*/
4181 if (mono_class_need_stelemref_method (klass)) {
4182 MonoMethod *method = mono_marshal_get_virtual_stelemref (klass);
4184 method->slot = stelemref_slot;
4186 g_assert (method->slot == stelemref_slot);
4188 vtable [stelemref_slot] = method;
4191 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4192 /* override interface methods */
4193 for (i = 0; i < onum; i++) {
4194 MonoMethod *decl = overrides [i*2];
4195 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4197 dslot = mono_method_get_vtable_slot (decl);
4199 mono_class_set_type_load_failure (klass, "");
4203 dslot += mono_class_interface_offset (klass, decl->klass);
4204 vtable [dslot] = overrides [i*2 + 1];
4205 vtable [dslot]->slot = dslot;
4207 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4209 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4211 if (mono_security_core_clr_enabled ())
4212 mono_security_core_clr_check_override (klass, vtable [dslot], decl);
4215 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4216 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4219 * Create a list of virtual methods to avoid calling
4220 * mono_class_get_virtual_methods () which is slow because of the metadata
4224 gpointer iter = NULL;
4227 virt_methods = NULL;
4228 while ((cm = mono_class_get_virtual_methods (klass, &iter))) {
4229 virt_methods = g_slist_prepend (virt_methods, cm);
4231 if (mono_class_has_failure (klass))
4235 // Loop on all implemented interfaces...
4236 for (i = 0; i < klass->interface_offsets_count; i++) {
4237 MonoClass *parent = klass->parent;
4239 gboolean interface_is_explicitly_implemented_by_class;
4242 ic = klass->interfaces_packed [i];
4243 ic_offset = mono_class_interface_offset (klass, ic);
4245 mono_class_setup_methods (ic);
4246 if (mono_class_has_failure (ic))
4249 // Check if this interface is explicitly implemented (instead of just inherited)
4250 if (parent != NULL) {
4251 int implemented_interfaces_index;
4252 interface_is_explicitly_implemented_by_class = FALSE;
4253 for (implemented_interfaces_index = 0; implemented_interfaces_index < klass->interface_count; implemented_interfaces_index++) {
4254 if (ic == klass->interfaces [implemented_interfaces_index]) {
4255 interface_is_explicitly_implemented_by_class = TRUE;
4260 interface_is_explicitly_implemented_by_class = TRUE;
4263 // Loop on all interface methods...
4264 int mcount = mono_class_get_method_count (ic);
4265 for (im_index = 0; im_index < mcount; im_index++) {
4266 MonoMethod *im = ic->methods [im_index];
4267 int im_slot = ic_offset + im->slot;
4268 MonoMethod *override_im = (override_map != NULL) ? (MonoMethod *)g_hash_table_lookup (override_map, im) : NULL;
4270 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4273 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4275 // If there is an explicit implementation, just use it right away,
4276 // otherwise look for a matching method
4277 if (override_im == NULL) {
4281 // First look for a suitable method among the class methods
4282 for (l = virt_methods; l; l = l->next) {
4283 cm = (MonoMethod *)l->data;
4284 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)));
4285 if (check_interface_method_override (klass, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
4286 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4287 vtable [im_slot] = cm;
4288 /* Why do we need this? */
4293 TRACE_INTERFACE_VTABLE (printf ("\n"));
4294 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4298 // If the slot is still empty, look in all the inherited virtual methods...
4299 if ((vtable [im_slot] == NULL) && klass->parent != NULL) {
4300 MonoClass *parent = klass->parent;
4301 // Reverse order, so that last added methods are preferred
4302 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4303 MonoMethod *cm = parent->vtable [cm_index];
4305 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));
4306 if ((cm != NULL) && check_interface_method_override (klass, im, cm, FALSE, FALSE, TRUE)) {
4307 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4308 vtable [im_slot] = cm;
4309 /* Why do we need this? */
4315 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4317 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4321 g_assert (vtable [im_slot] == override_im);
4326 // If the class is not abstract, check that all its interface slots are full.
4327 // The check is done here and not directly at the end of the loop above because
4328 // it can happen (for injected generic array interfaces) that the same slot is
4329 // processed multiple times (those interfaces have overlapping slots), and it
4330 // will not always be the first pass the one that fills the slot.
4331 if (!mono_class_is_abstract (klass)) {
4332 for (i = 0; i < klass->interface_offsets_count; i++) {
4336 ic = klass->interfaces_packed [i];
4337 ic_offset = mono_class_interface_offset (klass, ic);
4339 int mcount = mono_class_get_method_count (ic);
4340 for (im_index = 0; im_index < mcount; im_index++) {
4341 MonoMethod *im = ic->methods [im_index];
4342 int im_slot = ic_offset + im->slot;
4344 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4347 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4348 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4349 if (vtable [im_slot] == NULL) {
4350 print_unimplemented_interface_method_info (klass, ic, im, im_slot, overrides, onum);
4357 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4358 for (l = virt_methods; l; l = l->next) {
4359 cm = (MonoMethod *)l->data;
4361 * If the method is REUSE_SLOT, we must check in the
4362 * base class for a method to override.
4364 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4366 for (k = klass->parent; k ; k = k->parent) {
4371 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4372 MonoMethodSignature *cmsig, *m1sig;
4374 cmsig = mono_method_signature (cm);
4375 m1sig = mono_method_signature (m1);
4377 if (!cmsig || !m1sig) {
4378 /* FIXME proper error message */
4379 mono_class_set_type_load_failure (klass, "");
4383 if (!strcmp(cm->name, m1->name) &&
4384 mono_metadata_signature_equal (cmsig, m1sig)) {
4386 if (mono_security_core_clr_enabled ())
4387 mono_security_core_clr_check_override (klass, cm, m1);
4389 slot = mono_method_get_vtable_slot (m1);
4393 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4394 char *body_name = mono_method_full_name (cm, TRUE);
4395 char *decl_name = mono_method_full_name (m1, TRUE);
4396 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4402 g_assert (cm->slot < max_vtsize);
4404 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4405 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4406 mono_method_full_name (m1, 1), m1,
4407 mono_method_full_name (cm, 1), cm));
4408 g_hash_table_insert (override_map, m1, cm);
4412 if (mono_class_has_failure (k))
4422 /*Non final newslot methods must be given a non-interface vtable slot*/
4423 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4427 cm->slot = cur_slot++;
4429 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4430 vtable [cm->slot] = cm;
4433 /* override non interface methods */
4434 for (i = 0; i < onum; i++) {
4435 MonoMethod *decl = overrides [i*2];
4436 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4437 g_assert (decl->slot != -1);
4438 vtable [decl->slot] = overrides [i*2 + 1];
4439 overrides [i * 2 + 1]->slot = decl->slot;
4441 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4442 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4443 mono_method_full_name (decl, 1), decl,
4444 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4445 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4447 if (mono_security_core_clr_enabled ())
4448 mono_security_core_clr_check_override (klass, vtable [decl->slot], decl);
4453 * If a method occupies more than one place in the vtable, and it is
4454 * overriden, then change the other occurances too.
4459 for (i = 0; i < max_vtsize; ++i)
4461 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4463 cm = (MonoMethod *)g_hash_table_lookup (override_map, vtable [i]);
4468 g_hash_table_destroy (override_map);
4469 override_map = NULL;
4472 g_slist_free (virt_methods);
4473 virt_methods = NULL;
4475 g_assert (cur_slot <= max_vtsize);
4477 /* Ensure that all vtable slots are filled with concrete instance methods */
4478 if (!mono_class_is_abstract (klass)) {
4479 for (i = 0; i < cur_slot; ++i) {
4480 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4481 char *type_name = mono_type_get_full_name (klass);
4482 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4483 mono_class_set_type_load_failure (klass, "Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name);
4485 g_free (method_name);
4492 if (mono_class_is_ginst (klass)) {
4493 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4495 mono_class_init (gklass);
4497 klass->vtable_size = MAX (gklass->vtable_size, cur_slot);
4499 /* Check that the vtable_size value computed in mono_class_init () is correct */
4500 if (klass->vtable_size)
4501 g_assert (cur_slot == klass->vtable_size);
4502 klass->vtable_size = cur_slot;
4505 /* Try to share the vtable with our parent. */
4506 if (klass->parent && (klass->parent->vtable_size == klass->vtable_size) && (memcmp (klass->parent->vtable, vtable, sizeof (gpointer) * klass->vtable_size) == 0)) {
4507 mono_memory_barrier ();
4508 klass->vtable = klass->parent->vtable;
4510 MonoMethod **tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * klass->vtable_size);
4511 memcpy (tmp, vtable, sizeof (gpointer) * klass->vtable_size);
4512 mono_memory_barrier ();
4513 klass->vtable = tmp;
4516 DEBUG_INTERFACE_VTABLE (print_vtable_full (klass, klass->vtable, klass->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4517 if (mono_print_vtable) {
4520 print_implemented_interfaces (klass);
4522 for (i = 0; i <= max_iid; i++)
4523 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
4526 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&klass->byval_arg),
4527 klass->vtable_size, icount);
4529 for (i = 0; i < cur_slot; ++i) {
4534 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4535 mono_method_full_name (cm, TRUE));
4541 printf ("Interfaces %s.%s (max_iid = %d)\n", klass->name_space,
4542 klass->name, max_iid);
4544 for (i = 0; i < klass->interface_count; i++) {
4545 ic = klass->interfaces [i];
4546 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4547 mono_class_interface_offset (klass, ic),
4548 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4551 for (k = klass->parent; k ; k = k->parent) {
4552 for (i = 0; i < k->interface_count; i++) {
4553 ic = k->interfaces [i];
4554 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4555 mono_class_interface_offset (klass, ic),
4556 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4564 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (klass));
4569 char *name = mono_type_get_full_name (klass);
4570 mono_class_set_type_load_failure (klass, "VTable setup of type %s failed", name);
4574 g_hash_table_destroy (override_map);
4576 g_slist_free (virt_methods);
4581 * mono_method_get_vtable_slot:
4583 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4584 * LOCKING: Acquires the loader lock.
4586 * FIXME Use proper MonoError machinery here.
4589 mono_method_get_vtable_slot (MonoMethod *method)
4591 if (method->slot == -1) {
4592 mono_class_setup_vtable (method->klass);
4593 if (mono_class_has_failure (method->klass))
4595 if (method->slot == -1) {
4599 if (!mono_class_is_ginst (method->klass)) {
4600 g_assert (method->is_inflated);
4601 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4604 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4605 g_assert (mono_class_is_ginst (method->klass));
4606 gklass = mono_class_get_generic_class (method->klass)->container_class;
4607 mono_class_setup_methods (method->klass);
4608 g_assert (method->klass->methods);
4609 mcount = mono_class_get_method_count (method->klass);
4610 for (i = 0; i < mcount; ++i) {
4611 if (method->klass->methods [i] == method)
4614 g_assert (i < mcount);
4615 g_assert (gklass->methods);
4616 method->slot = gklass->methods [i]->slot;
4618 g_assert (method->slot != -1);
4620 return method->slot;
4624 * mono_method_get_vtable_index:
4627 * Returns the index into the runtime vtable to access the method or,
4628 * in the case of a virtual generic method, the virtual generic method
4629 * thunk. Returns -1 on failure.
4631 * FIXME Use proper MonoError machinery here.
4634 mono_method_get_vtable_index (MonoMethod *method)
4636 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4637 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4638 if (imethod->declaring->is_generic)
4639 return mono_method_get_vtable_slot (imethod->declaring);
4641 return mono_method_get_vtable_slot (method);
4644 static MonoMethod *default_ghc = NULL;
4645 static MonoMethod *default_finalize = NULL;
4646 static int finalize_slot = -1;
4647 static int ghc_slot = -1;
4650 initialize_object_slots (MonoClass *klass)
4655 if (klass == mono_defaults.object_class) {
4656 mono_class_setup_vtable (klass);
4657 for (i = 0; i < klass->vtable_size; ++i) {
4658 MonoMethod *cm = klass->vtable [i];
4660 if (!strcmp (cm->name, "GetHashCode"))
4662 else if (!strcmp (cm->name, "Finalize"))
4666 g_assert (ghc_slot > 0);
4667 default_ghc = klass->vtable [ghc_slot];
4669 g_assert (finalize_slot > 0);
4670 default_finalize = klass->vtable [finalize_slot];
4675 MonoMethod *array_method;
4677 } GenericArrayMethodInfo;
4679 static int generic_array_method_num = 0;
4680 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4683 generic_array_methods (MonoClass *klass)
4685 int i, count_generic = 0, mcount;
4686 GList *list = NULL, *tmp;
4687 if (generic_array_method_num)
4688 return generic_array_method_num;
4689 mono_class_setup_methods (klass->parent); /*This is setting up System.Array*/
4690 g_assert (!mono_class_has_failure (klass->parent)); /*So hitting this assert is a huge problem*/
4691 mcount = mono_class_get_method_count (klass->parent);
4692 for (i = 0; i < mcount; i++) {
4693 MonoMethod *m = klass->parent->methods [i];
4694 if (!strncmp (m->name, "InternalArray__", 15)) {
4696 list = g_list_prepend (list, m);
4699 list = g_list_reverse (list);
4700 generic_array_method_info = (GenericArrayMethodInfo *)mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4702 for (tmp = list; tmp; tmp = tmp->next) {
4703 const char *mname, *iname;
4705 MonoMethod *m = (MonoMethod *)tmp->data;
4706 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4707 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4709 generic_array_method_info [i].array_method = m;
4710 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4711 iname = "System.Collections.Generic.ICollection`1.";
4712 mname = m->name + 27;
4713 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4714 iname = "System.Collections.Generic.IEnumerable`1.";
4715 mname = m->name + 27;
4716 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4717 iname = "System.Collections.Generic.IReadOnlyList`1.";
4718 mname = m->name + strlen (ireadonlylist_prefix);
4719 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4720 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4721 mname = m->name + strlen (ireadonlycollection_prefix);
4722 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4723 iname = "System.Collections.Generic.IList`1.";
4724 mname = m->name + 15;
4726 g_assert_not_reached ();
4729 name = (gchar *)mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4730 strcpy (name, iname);
4731 strcpy (name + strlen (iname), mname);
4732 generic_array_method_info [i].name = name;
4735 /*g_print ("array generic methods: %d\n", count_generic);*/
4737 generic_array_method_num = count_generic;
4739 return generic_array_method_num;
4743 setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos)
4745 MonoGenericContext tmp_context;
4748 tmp_context.class_inst = NULL;
4749 tmp_context.method_inst = mono_class_get_generic_class (iface)->context.class_inst;
4750 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
4752 for (i = 0; i < generic_array_method_num; i++) {
4754 MonoMethod *m = generic_array_method_info [i].array_method;
4755 MonoMethod *inflated;
4757 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
4758 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
4759 methods [pos++] = mono_marshal_get_generic_array_helper (klass, iface, generic_array_method_info [i].name, inflated);
4764 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
4766 int null_length = strlen ("(null)");
4767 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
4768 char *s = (char *)mono_image_alloc (image, len);
4771 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
4772 g_assert (result == len - 1);
4779 * @klass: the class to initialize
4781 * Compute the instance_size, class_size and other infos that cannot be
4782 * computed at mono_class_get() time. Also compute vtable_size if possible.
4783 * Returns TRUE on success or FALSE if there was a problem in loading
4784 * the type (incorrect assemblies, missing assemblies, methods, etc).
4785 * Initializes the following fields in @klass:
4786 * - all the fields initialized by mono_class_init_sizes ()
4791 * LOCKING: Acquires the loader lock.
4794 mono_class_init (MonoClass *klass)
4796 int i, vtable_size = 0, array_method_count = 0;
4797 MonoCachedClassInfo cached_info;
4798 gboolean has_cached_info;
4799 gboolean locked = FALSE;
4800 gboolean ghcimpl = FALSE;
4801 gboolean has_cctor = FALSE;
4802 int first_iface_slot = 0;
4806 /* Double-checking locking pattern */
4807 if (klass->inited || mono_class_has_failure (klass))
4808 return !mono_class_has_failure (klass);
4810 /*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/
4813 * This function can recursively call itself.
4815 GSList *init_list = (GSList *)mono_native_tls_get_value (init_pending_tls_id);
4816 if (g_slist_find (init_list, klass)) {
4817 mono_class_set_type_load_failure (klass, "Recursive type definition detected");
4820 init_list = g_slist_prepend (init_list, klass);
4821 mono_native_tls_set_value (init_pending_tls_id, init_list);
4824 * We want to avoid doing complicated work inside locks, so we compute all the required
4825 * information and write it to @klass inside a lock.
4828 if (mono_verifier_is_enabled_for_class (klass) && !mono_verifier_verify_class (klass)) {
4829 mono_class_set_type_load_failure (klass, "%s", concat_two_strings_with_zero (klass->image, klass->name, klass->image->assembly_name));
4833 if (klass->byval_arg.type == MONO_TYPE_ARRAY || klass->byval_arg.type == MONO_TYPE_SZARRAY) {
4834 MonoClass *element_class = klass->element_class;
4835 if (!element_class->inited)
4836 mono_class_init (element_class);
4837 if (mono_class_set_type_load_failure_causedby_class (klass, element_class, "Could not load array element class"))
4841 mono_stats.initialized_class_count++;
4843 if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic) {
4844 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4846 mono_class_init (gklass);
4847 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic Type Definition failed to init"))
4850 mono_class_setup_interface_id (klass);
4853 if (klass->parent && !klass->parent->inited)
4854 mono_class_init (klass->parent);
4856 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
4858 /* Compute instance size etc. */
4859 init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
4860 if (mono_class_has_failure (klass))
4863 mono_class_setup_supertypes (klass);
4866 initialize_object_slots (klass);
4869 * Initialize the rest of the data without creating a generic vtable if possible.
4870 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
4871 * also avoid computing a generic vtable.
4873 if (has_cached_info) {
4875 vtable_size = cached_info.vtable_size;
4876 ghcimpl = cached_info.ghcimpl;
4877 has_cctor = cached_info.has_cctor;
4878 } else if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
4879 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
4880 * The first slot if for array with.
4882 static int szarray_vtable_size[2] = { 0 };
4884 int slot = MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg) ? 0 : 1;
4887 if (!szarray_vtable_size [slot]) {
4888 mono_class_setup_vtable (klass);
4889 szarray_vtable_size [slot] = klass->vtable_size;
4890 vtable_size = klass->vtable_size;
4892 vtable_size = szarray_vtable_size[slot];
4894 } else if (mono_class_is_ginst (klass) && !MONO_CLASS_IS_INTERFACE (klass)) {
4895 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4897 /* Generic instance case */
4898 ghcimpl = gklass->ghcimpl;
4899 has_cctor = gklass->has_cctor;
4901 mono_class_setup_vtable (gklass);
4902 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to init"))
4905 vtable_size = gklass->vtable_size;
4909 /* ghcimpl is not currently used
4911 if (klass->parent) {
4912 MonoMethod *cmethod = klass->vtable [ghc_slot];
4913 if (cmethod->is_inflated)
4914 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
4915 if (cmethod == default_ghc) {
4921 /* C# doesn't allow interfaces to have cctors */
4922 if (!MONO_CLASS_IS_INTERFACE (klass) || klass->image != mono_defaults.corlib) {
4923 MonoMethod *cmethod = NULL;
4925 if (mono_class_is_ginst (klass)) {
4926 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4928 /* Generic instance case */
4929 ghcimpl = gklass->ghcimpl;
4930 has_cctor = gklass->has_cctor;
4931 } else if (klass->type_token && !image_is_dynamic(klass->image)) {
4932 cmethod = find_method_in_metadata (klass, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
4933 /* The find_method function ignores the 'flags' argument */
4934 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
4937 mono_class_setup_methods (klass);
4938 if (mono_class_has_failure (klass))
4941 int mcount = mono_class_get_method_count (klass);
4942 for (i = 0; i < mcount; ++i) {
4943 MonoMethod *method = klass->methods [i];
4944 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
4945 (strcmp (".cctor", method->name) == 0)) {
4955 array_method_count = 3 + (klass->rank > 1? 2: 1);
4957 if (klass->interface_count) {
4958 int count_generic = generic_array_methods (klass);
4959 array_method_count += klass->interface_count * count_generic;
4963 if (klass->parent) {
4964 if (!klass->parent->vtable_size)
4965 mono_class_setup_vtable (klass->parent);
4966 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class vtable failed to initialize"))
4968 g_assert (klass->parent->vtable_size);
4969 first_iface_slot = klass->parent->vtable_size;
4970 if (mono_class_need_stelemref_method (klass))
4975 * Do the actual changes to @klass inside the loader lock
4977 mono_loader_lock ();
4980 if (klass->inited || mono_class_has_failure (klass)) {
4981 mono_loader_unlock ();
4982 /* Somebody might have gotten in before us */
4983 return !mono_class_has_failure (klass);
4986 mono_stats.initialized_class_count++;
4988 if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic)
4989 mono_stats.generic_class_count++;
4991 if (mono_class_is_ginst (klass) || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
4992 klass->nested_classes_inited = TRUE;
4993 klass->ghcimpl = ghcimpl;
4994 klass->has_cctor = has_cctor;
4996 klass->vtable_size = vtable_size;
4997 if (has_cached_info) {
4998 klass->has_finalize = cached_info.has_finalize;
4999 klass->has_finalize_inited = TRUE;
5002 mono_class_set_method_count (klass, array_method_count);
5004 mono_loader_unlock ();
5007 setup_interface_offsets (klass, first_iface_slot, TRUE);
5009 if (mono_security_core_clr_enabled ())
5010 mono_security_core_clr_check_inheritance (klass);
5012 if (mono_class_is_ginst (klass) && !mono_verifier_class_is_valid_generic_instantiation (klass))
5013 mono_class_set_type_load_failure (klass, "Invalid generic instantiation");
5018 init_list = g_slist_remove (init_list, klass);
5019 mono_native_tls_set_value (init_pending_tls_id, init_list);
5022 mono_loader_unlock ();
5024 /* Leave this for last */
5025 mono_loader_lock ();
5027 mono_loader_unlock ();
5029 return !mono_class_has_failure (klass);
5033 * mono_class_has_finalizer:
5035 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5039 mono_class_has_finalizer (MonoClass *klass)
5041 gboolean has_finalize = FALSE;
5043 if (klass->has_finalize_inited)
5044 return klass->has_finalize;
5046 /* Interfaces and valuetypes are not supposed to have finalizers */
5047 if (!(MONO_CLASS_IS_INTERFACE (klass) || klass->valuetype)) {
5048 MonoMethod *cmethod = NULL;
5050 if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5051 } else if (mono_class_is_ginst (klass)) {
5052 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5054 has_finalize = mono_class_has_finalizer (gklass);
5055 } else if (klass->parent && klass->parent->has_finalize) {
5056 has_finalize = TRUE;
5058 if (klass->parent) {
5060 * Can't search in metadata for a method named Finalize, because that
5061 * ignores overrides.
5063 mono_class_setup_vtable (klass);
5064 if (mono_class_has_failure (klass))
5067 cmethod = klass->vtable [finalize_slot];
5071 g_assert (klass->vtable_size > finalize_slot);
5073 if (klass->parent) {
5074 if (cmethod->is_inflated)
5075 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5076 if (cmethod != default_finalize)
5077 has_finalize = TRUE;
5083 mono_image_lock (klass->image);
5085 if (!klass->has_finalize_inited) {
5086 klass->has_finalize = has_finalize ? 1 : 0;
5088 mono_memory_barrier ();
5089 klass->has_finalize_inited = TRUE;
5092 mono_image_unlock (klass->image);
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);
5746 mono_class_setup_parent (klass, klass->parent);
5748 if (klass->enumtype) {
5749 klass->cast_class = gtd->cast_class;
5750 klass->element_class = gtd->element_class;
5755 mono_type_is_primitive (MonoType *type)
5757 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
5758 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
5762 * Create the `MonoClass' for an instantiation of a generic type.
5763 * We only do this if we actually need it.
5766 mono_generic_class_get_class (MonoGenericClass *gclass)
5768 MonoClass *klass, *gklass;
5770 if (gclass->cached_class)
5771 return gclass->cached_class;
5773 klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClassGenericInst));
5775 gklass = gclass->container_class;
5777 if (gklass->nested_in) {
5778 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
5779 klass->nested_in = gklass->nested_in;
5782 klass->name = gklass->name;
5783 klass->name_space = gklass->name_space;
5785 klass->image = gklass->image;
5786 klass->type_token = gklass->type_token;
5788 klass->class_kind = MONO_CLASS_GINST;
5790 ((MonoClassGenericInst*)klass)->generic_class = gclass;
5792 klass->byval_arg.type = MONO_TYPE_GENERICINST;
5793 klass->this_arg.type = klass->byval_arg.type;
5794 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
5795 klass->this_arg.byref = TRUE;
5796 klass->enumtype = gklass->enumtype;
5797 klass->valuetype = gklass->valuetype;
5800 if (gklass->image->assembly_name && !strcmp (gklass->image->assembly_name, "System.Numerics.Vectors") && !strcmp (gklass->name_space, "System.Numerics") && !strcmp (gklass->name, "Vector`1")) {
5801 g_assert (gclass->context.class_inst);
5802 g_assert (gclass->context.class_inst->type_argc > 0);
5803 if (mono_type_is_primitive (gclass->context.class_inst->type_argv [0]))
5804 klass->simd_type = 1;
5806 klass->is_array_special_interface = gklass->is_array_special_interface;
5808 klass->cast_class = klass->element_class = klass;
5810 if (gclass->is_dynamic) {
5812 * 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.
5813 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
5814 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
5816 if (!gklass->wastypebuilder)
5819 if (klass->enumtype) {
5821 * For enums, gklass->fields might not been set, but instance_size etc. is
5822 * already set in mono_reflection_create_internal_class (). For non-enums,
5823 * these will be computed normally in mono_class_layout_fields ().
5825 klass->instance_size = gklass->instance_size;
5826 klass->sizes.class_size = gklass->sizes.class_size;
5827 klass->size_inited = 1;
5831 mono_loader_lock ();
5833 if (gclass->cached_class) {
5834 mono_loader_unlock ();
5835 return gclass->cached_class;
5838 if (record_gclass_instantiation > 0)
5839 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
5841 if (mono_class_is_nullable (klass))
5842 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
5844 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5846 mono_generic_class_setup_parent (klass, gklass);
5848 if (gclass->is_dynamic)
5849 mono_class_setup_supertypes (klass);
5851 mono_memory_barrier ();
5852 gclass->cached_class = klass;
5854 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5856 ++class_ginst_count;
5857 inflated_classes_size += sizeof (MonoClassGenericInst);
5859 mono_loader_unlock ();
5865 get_image_for_container (MonoGenericContainer *container)
5868 if (container->is_anonymous) {
5869 result = container->owner.image;
5872 if (container->is_method) {
5873 MonoMethod *method = container->owner.method;
5874 g_assert_checked (method);
5875 klass = method->klass;
5877 klass = container->owner.klass;
5879 g_assert_checked (klass);
5880 result = klass->image;
5887 get_image_for_generic_param (MonoGenericParam *param)
5889 MonoGenericContainer *container = mono_generic_param_owner (param);
5890 g_assert_checked (container);
5891 return get_image_for_container (container);
5894 // Make a string in the designated image consisting of a single integer.
5895 #define INT_STRING_SIZE 16
5897 make_generic_name_string (MonoImage *image, int num)
5899 char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
5900 g_snprintf (name, INT_STRING_SIZE, "%d", num);
5904 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
5905 // pinfo is derived from param by the caller for us.
5907 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
5909 MonoClass *klass, **ptr;
5911 MonoGenericContainer *container = mono_generic_param_owner (param);
5912 g_assert_checked (container);
5914 MonoImage *image = get_image_for_container (container);
5915 gboolean is_mvar = container->is_method;
5916 gboolean is_anonymous = container->is_anonymous;
5918 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassGenericParam));
5919 klass->class_kind = MONO_CLASS_GPARAM;
5920 classes_size += sizeof (MonoClassGenericParam);
5921 ++class_gparam_count;
5924 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
5926 int n = mono_generic_param_num (param);
5927 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
5931 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , "" );
5932 } else if (is_mvar) {
5933 MonoMethod *omethod = container->owner.method;
5934 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
5936 MonoClass *oklass = container->owner.klass;
5937 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
5940 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5942 // Count non-NULL items in pinfo->constraints
5945 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
5949 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
5950 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
5952 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
5953 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
5955 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
5958 if (count - pos > 0) {
5959 klass->interface_count = count - pos;
5960 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
5961 klass->interfaces_inited = TRUE;
5962 for (i = pos; i < count; i++)
5963 CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
5966 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
5968 klass->inited = TRUE;
5969 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class , klass );
5970 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
5972 klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
5973 klass->this_arg.type = klass->byval_arg.type;
5974 CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param , param );
5975 CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
5976 klass->this_arg.byref = TRUE;
5978 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
5979 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
5981 /*Init these fields to sane values*/
5982 klass->min_align = 1;
5984 * This makes sure the the value size of this class is equal to the size of the types the gparam is
5985 * constrained to, the JIT depends on this.
5987 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
5988 mono_memory_barrier ();
5989 klass->size_inited = 1;
5991 mono_class_setup_supertypes (klass);
5993 if (count - pos > 0) {
5994 mono_class_setup_vtable (klass->parent);
5995 if (mono_class_has_failure (klass->parent))
5996 mono_class_set_type_load_failure (klass, "Failed to setup parent interfaces");
5998 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6004 #define FAST_CACHE_SIZE 16
6007 * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6008 * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6009 * we cache the MonoClasses.
6010 * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6011 * LOCKING: Takes the image lock depending on @take_lock.
6014 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6016 int n = mono_generic_param_num (param);
6017 MonoImage *image = get_image_for_generic_param (param);
6018 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6019 MonoClass *klass = NULL;
6024 // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6025 // For high numbers or constraints we have to use pointer hashes.
6026 if (param->gshared_constraint) {
6027 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6030 mono_image_lock (image);
6031 klass = (MonoClass *)g_hash_table_lookup (ht, param);
6033 mono_image_unlock (image);
6038 if (n < FAST_CACHE_SIZE) {
6040 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6042 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6044 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6047 mono_image_lock (image);
6048 klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6050 mono_image_unlock (image);
6057 * LOCKING: Image lock (param->image) must be held
6060 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6062 int n = mono_generic_param_num (param);
6063 MonoImage *image = get_image_for_generic_param (param);
6064 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6068 if (param->gshared_constraint) {
6069 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6071 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6072 mono_memory_barrier ();
6074 image->mvar_cache_constrained = ht;
6076 image->var_cache_constrained = ht;
6078 g_hash_table_insert (ht, param, klass);
6079 } else if (n < FAST_CACHE_SIZE) {
6081 /* Requires locking to avoid droping an already published class */
6082 if (!image->mvar_cache_fast)
6083 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6084 image->mvar_cache_fast [n] = klass;
6086 if (!image->var_cache_fast)
6087 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6088 image->var_cache_fast [n] = klass;
6091 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6093 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6095 ht = g_hash_table_new (NULL, NULL);
6096 mono_memory_barrier ();
6098 image->mvar_cache_slow = ht;
6100 image->var_cache_slow = ht;
6103 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6108 * LOCKING: Acquires the image lock (@image).
6111 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6113 MonoImage *image = get_image_for_generic_param (param);
6114 MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6115 MonoClass *klass, *klass2;
6117 // If a klass already exists for this object and is cached, return it.
6118 if (pinfo) // Non-anonymous
6119 klass = pinfo->pklass;
6121 klass = get_anon_gparam_class (param, TRUE);
6126 // Create a new klass
6127 klass = make_generic_param_class (param, pinfo);
6129 // Now we need to cache the klass we created.
6130 // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6131 // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6132 // and allow our newly-created klass object to just leak.
6133 mono_memory_barrier ();
6135 mono_image_lock (image);
6137 // Here "klass2" refers to the klass potentially created by the other thread.
6138 if (pinfo) // Repeat check from above
6139 klass2 = pinfo->pklass;
6141 klass2 = get_anon_gparam_class (param, FALSE);
6148 pinfo->pklass = klass;
6150 set_anon_gparam_class (param, klass);
6152 mono_image_unlock (image);
6154 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6156 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED); // Alert profiler about botched class create
6158 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6164 * mono_class_from_generic_parameter:
6165 * @param: Parameter to find/construct a class for.
6166 * @arg2: Is ignored.
6167 * @arg3: Is ignored.
6170 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6172 return mono_class_from_generic_parameter_internal (param);
6176 mono_ptr_class_get (MonoType *type)
6179 MonoClass *el_class;
6183 el_class = mono_class_from_mono_type (type);
6184 image = el_class->image;
6186 mono_image_lock (image);
6187 if (image->ptr_cache) {
6188 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6189 mono_image_unlock (image);
6193 mono_image_unlock (image);
6195 result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassPointer));
6197 classes_size += sizeof (MonoClassPointer);
6198 ++class_pointer_count;
6200 result->parent = NULL; /* no parent for PTR types */
6201 result->name_space = el_class->name_space;
6202 name = g_strdup_printf ("%s*", el_class->name);
6203 result->name = mono_image_strdup (image, name);
6204 result->class_kind = MONO_CLASS_POINTER;
6207 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6209 result->image = el_class->image;
6210 result->inited = TRUE;
6211 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6212 result->cast_class = result->element_class = el_class;
6213 result->blittable = TRUE;
6215 result->byval_arg.type = MONO_TYPE_PTR;
6216 result->this_arg.type = result->byval_arg.type;
6217 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6218 result->this_arg.byref = TRUE;
6220 mono_class_setup_supertypes (result);
6222 mono_image_lock (image);
6223 if (image->ptr_cache) {
6225 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6226 mono_image_unlock (image);
6227 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6231 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6233 g_hash_table_insert (image->ptr_cache, el_class, result);
6234 mono_image_unlock (image);
6236 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6242 mono_fnptr_class_get (MonoMethodSignature *sig)
6244 MonoClass *result, *cached;
6245 static GHashTable *ptr_hash = NULL;
6247 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6249 mono_loader_lock ();
6251 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6252 cached = (MonoClass *)g_hash_table_lookup (ptr_hash, sig);
6253 mono_loader_unlock ();
6257 result = g_new0 (MonoClass, 1);
6259 result->parent = NULL; /* no parent for PTR types */
6260 result->name_space = "System";
6261 result->name = "MonoFNPtrFakeClass";
6262 result->class_kind = MONO_CLASS_POINTER;
6264 result->image = mono_defaults.corlib; /* need to fix... */
6265 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6266 result->cast_class = result->element_class = result;
6267 result->byval_arg.type = MONO_TYPE_FNPTR;
6268 result->this_arg.type = result->byval_arg.type;
6269 result->this_arg.data.method = result->byval_arg.data.method = sig;
6270 result->this_arg.byref = TRUE;
6271 result->blittable = TRUE;
6272 result->inited = TRUE;
6274 mono_class_setup_supertypes (result);
6276 mono_loader_lock ();
6278 cached = (MonoClass *)g_hash_table_lookup (ptr_hash, sig);
6281 mono_loader_unlock ();
6285 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6287 classes_size += sizeof (MonoClassPointer);
6288 ++class_pointer_count;
6290 g_hash_table_insert (ptr_hash, sig, result);
6292 mono_loader_unlock ();
6294 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6300 * mono_class_from_mono_type:
6301 * @type: describes the type to return
6303 * This returns a MonoClass for the specified MonoType, the value is never NULL.
6306 mono_class_from_mono_type (MonoType *type)
6308 switch (type->type) {
6309 case MONO_TYPE_OBJECT:
6310 return type->data.klass? type->data.klass: mono_defaults.object_class;
6311 case MONO_TYPE_VOID:
6312 return type->data.klass? type->data.klass: mono_defaults.void_class;
6313 case MONO_TYPE_BOOLEAN:
6314 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6315 case MONO_TYPE_CHAR:
6316 return type->data.klass? type->data.klass: mono_defaults.char_class;
6318 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6320 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6322 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6324 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6326 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6328 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6330 return type->data.klass? type->data.klass: mono_defaults.int_class;
6332 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6334 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6336 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6338 return type->data.klass? type->data.klass: mono_defaults.single_class;
6340 return type->data.klass? type->data.klass: mono_defaults.double_class;
6341 case MONO_TYPE_STRING:
6342 return type->data.klass? type->data.klass: mono_defaults.string_class;
6343 case MONO_TYPE_TYPEDBYREF:
6344 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6345 case MONO_TYPE_ARRAY:
6346 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6348 return mono_ptr_class_get (type->data.type);
6349 case MONO_TYPE_FNPTR:
6350 return mono_fnptr_class_get (type->data.method);
6351 case MONO_TYPE_SZARRAY:
6352 return mono_array_class_get (type->data.klass, 1);
6353 case MONO_TYPE_CLASS:
6354 case MONO_TYPE_VALUETYPE:
6355 return type->data.klass;
6356 case MONO_TYPE_GENERICINST:
6357 return mono_generic_class_get_class (type->data.generic_class);
6358 case MONO_TYPE_MVAR:
6360 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6362 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6363 g_assert_not_reached ();
6366 // Yes, this returns NULL, even if it is documented as not doing so, but there
6367 // is no way for the code to make it this far, due to the assert above.
6372 * mono_type_retrieve_from_typespec
6373 * @image: context where the image is created
6374 * @type_spec: typespec token
6375 * @context: the generic context used to evaluate generic instantiations in
6378 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6380 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6382 *did_inflate = FALSE;
6387 if (context && (context->class_inst || context->method_inst)) {
6388 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6390 if (!mono_error_ok (error)) {
6396 *did_inflate = TRUE;
6403 * mono_class_create_from_typespec
6404 * @image: context where the image is created
6405 * @type_spec: typespec token
6406 * @context: the generic context used to evaluate generic instantiations in
6409 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6412 gboolean inflated = FALSE;
6413 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6414 return_val_if_nok (error, NULL);
6415 ret = mono_class_from_mono_type (t);
6417 mono_metadata_free_type (t);
6422 * mono_bounded_array_class_get:
6423 * @element_class: element class
6424 * @rank: the dimension of the array class
6425 * @bounded: whenever the array has non-zero bounds
6427 * Returns: A class object describing the array with element type @element_type and
6431 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6434 MonoClass *klass, *cached, *k;
6435 MonoClass *parent = NULL;
6436 GSList *list, *rootlist = NULL;
6440 g_assert (rank <= 255);
6443 /* bounded only matters for one-dimensional arrays */
6446 image = eclass->image;
6450 if (rank == 1 && !bounded) {
6452 * This case is very frequent not just during compilation because of calls
6453 * from mono_class_from_mono_type (), mono_array_new (),
6454 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6456 mono_os_mutex_lock (&image->szarray_cache_lock);
6457 if (!image->szarray_cache)
6458 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6459 cached = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6460 mono_os_mutex_unlock (&image->szarray_cache_lock);
6462 mono_loader_lock ();
6463 if (!image->array_cache)
6464 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6465 rootlist = (GSList *)g_hash_table_lookup (image->array_cache, eclass);
6466 for (list = rootlist; list; list = list->next) {
6467 k = (MonoClass *)list->data;
6468 if ((k->rank == rank) && (k->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6473 mono_loader_unlock ();
6478 parent = mono_defaults.array_class;
6479 if (!parent->inited)
6480 mono_class_init (parent);
6482 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassArray));
6484 klass->image = image;
6485 klass->name_space = eclass->name_space;
6486 klass->class_kind = MONO_CLASS_ARRAY;
6488 nsize = strlen (eclass->name);
6489 name = (char *)g_malloc (nsize + 2 + rank + 1);
6490 memcpy (name, eclass->name, nsize);
6493 memset (name + nsize + 1, ',', rank - 1);
6495 name [nsize + rank] = '*';
6496 name [nsize + rank + bounded] = ']';
6497 name [nsize + rank + bounded + 1] = 0;
6498 klass->name = mono_image_strdup (image, name);
6501 klass->type_token = 0;
6502 klass->parent = parent;
6503 klass->instance_size = mono_class_instance_size (klass->parent);
6505 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6506 /*Arrays of those two types are invalid.*/
6507 MonoError prepared_error;
6508 mono_error_init (&prepared_error);
6509 mono_error_set_invalid_program (&prepared_error, "Arrays of void or System.TypedReference types are invalid.");
6510 mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6511 mono_error_cleanup (&prepared_error);
6512 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6513 guint32 ref_info_handle = mono_class_get_ref_info_handle (eclass);
6514 if (!ref_info_handle || eclass->wastypebuilder) {
6515 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6516 g_assert (ref_info_handle && !eclass->wastypebuilder);
6518 /* element_size -1 is ok as this is not an instantitable type*/
6519 klass->sizes.element_size = -1;
6521 klass->sizes.element_size = mono_class_array_element_size (eclass);
6523 mono_class_setup_supertypes (klass);
6525 if (mono_class_is_ginst (eclass))
6526 mono_class_init (eclass);
6527 if (!eclass->size_inited)
6528 mono_class_setup_fields (eclass);
6529 mono_class_set_type_load_failure_causedby_class (klass, eclass, "Could not load array element type");
6530 /*FIXME we fail the array type, but we have to let other fields be set.*/
6532 klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6536 if (eclass->enumtype)
6537 klass->cast_class = eclass->element_class;
6539 klass->cast_class = eclass;
6541 switch (klass->cast_class->byval_arg.type) {
6543 klass->cast_class = mono_defaults.byte_class;
6546 klass->cast_class = mono_defaults.int16_class;
6549 #if SIZEOF_VOID_P == 4
6553 klass->cast_class = mono_defaults.int32_class;
6556 #if SIZEOF_VOID_P == 8
6560 klass->cast_class = mono_defaults.int64_class;
6566 klass->element_class = eclass;
6568 if ((rank > 1) || bounded) {
6569 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6570 klass->byval_arg.type = MONO_TYPE_ARRAY;
6571 klass->byval_arg.data.array = at;
6572 at->eklass = eclass;
6574 /* FIXME: complete.... */
6576 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6577 klass->byval_arg.data.klass = eclass;
6579 klass->this_arg = klass->byval_arg;
6580 klass->this_arg.byref = 1;
6582 mono_loader_lock ();
6584 /* Check cache again */
6586 if (rank == 1 && !bounded) {
6587 mono_os_mutex_lock (&image->szarray_cache_lock);
6588 cached = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6589 mono_os_mutex_unlock (&image->szarray_cache_lock);
6591 rootlist = (GSList *)g_hash_table_lookup (image->array_cache, eclass);
6592 for (list = rootlist; list; list = list->next) {
6593 k = (MonoClass *)list->data;
6594 if ((k->rank == rank) && (k->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6601 mono_loader_unlock ();
6605 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6607 classes_size += sizeof (MonoClassArray);
6608 ++class_array_count;
6610 if (rank == 1 && !bounded) {
6611 mono_os_mutex_lock (&image->szarray_cache_lock);
6612 g_hash_table_insert (image->szarray_cache, eclass, klass);
6613 mono_os_mutex_unlock (&image->szarray_cache_lock);
6615 list = g_slist_append (rootlist, klass);
6616 g_hash_table_insert (image->array_cache, eclass, list);
6619 mono_loader_unlock ();
6621 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6627 * mono_array_class_get:
6628 * @element_class: element class
6629 * @rank: the dimension of the array class
6631 * Returns: A class object describing the array with element type @element_type and
6635 mono_array_class_get (MonoClass *eclass, guint32 rank)
6637 return mono_bounded_array_class_get (eclass, rank, FALSE);
6641 * mono_class_instance_size:
6644 * Use to get the size of a class in bytes.
6646 * Returns: The size of an object instance
6649 mono_class_instance_size (MonoClass *klass)
6651 if (!klass->size_inited)
6652 mono_class_init (klass);
6654 return klass->instance_size;
6658 * mono_class_min_align:
6661 * Use to get the computed minimum alignment requirements for the specified class.
6663 * Returns: minimum alignment requirements
6666 mono_class_min_align (MonoClass *klass)
6668 if (!klass->size_inited)
6669 mono_class_init (klass);
6671 return klass->min_align;
6675 * mono_class_value_size:
6678 * This function is used for value types, and return the
6679 * space and the alignment to store that kind of value object.
6681 * Returns: the size of a value of kind @klass
6684 mono_class_value_size (MonoClass *klass, guint32 *align)
6688 /* fixme: check disable, because we still have external revereces to
6689 * mscorlib and Dummy Objects
6691 /*g_assert (klass->valuetype);*/
6693 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6696 *align = klass->min_align;
6702 * mono_class_data_size:
6705 * Returns: The size of the static class data
6708 mono_class_data_size (MonoClass *klass)
6711 mono_class_init (klass);
6712 /* This can happen with dynamically created types */
6713 if (!klass->fields_inited)
6714 mono_class_setup_fields (klass);
6716 /* in arrays, sizes.class_size is unioned with element_size
6717 * and arrays have no static fields
6721 return klass->sizes.class_size;
6725 * Auxiliary routine to mono_class_get_field
6727 * Takes a field index instead of a field token.
6729 static MonoClassField *
6730 mono_class_get_field_idx (MonoClass *klass, int idx)
6732 mono_class_setup_fields (klass);
6733 if (mono_class_has_failure (klass))
6737 int first_field_idx = mono_class_get_first_field_idx (klass);
6738 int fcount = mono_class_get_field_count (klass);
6739 if (klass->image->uncompressed_metadata) {
6741 * first_field_idx points to the FieldPtr table, while idx points into the
6742 * Field table, so we have to do a search.
6744 /*FIXME this is broken for types with multiple fields with the same name.*/
6745 const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6748 for (i = 0; i < fcount; ++i)
6749 if (mono_field_get_name (&klass->fields [i]) == name)
6750 return &klass->fields [i];
6751 g_assert_not_reached ();
6754 if ((idx >= first_field_idx) && (idx < first_field_idx + fcount)){
6755 return &klass->fields [idx - first_field_idx];
6759 klass = klass->parent;
6765 * mono_class_get_field:
6766 * @class: the class to lookup the field.
6767 * @field_token: the field token
6769 * Returns: A MonoClassField representing the type and offset of
6770 * the field, or a NULL value if the field does not belong to this
6774 mono_class_get_field (MonoClass *klass, guint32 field_token)
6776 int idx = mono_metadata_token_index (field_token);
6778 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6780 return mono_class_get_field_idx (klass, idx - 1);
6784 * mono_class_get_field_from_name:
6785 * @klass: the class to lookup the field.
6786 * @name: the field name
6788 * Search the class @klass and it's parents for a field with the name @name.
6790 * Returns: The MonoClassField pointer of the named field or NULL
6793 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6795 return mono_class_get_field_from_name_full (klass, name, NULL);
6799 * mono_class_get_field_from_name_full:
6800 * @klass: the class to lookup the field.
6801 * @name: the field name
6802 * @type: the type of the fields. This optional.
6804 * Search the class @klass and it's parents for a field with the name @name and type @type.
6806 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
6807 * of its generic type definition.
6809 * Returns: The MonoClassField pointer of the named field or NULL
6812 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6816 mono_class_setup_fields (klass);
6817 if (mono_class_has_failure (klass))
6821 int fcount = mono_class_get_field_count (klass);
6822 for (i = 0; i < fcount; ++i) {
6823 MonoClassField *field = &klass->fields [i];
6825 if (strcmp (name, mono_field_get_name (field)) != 0)
6829 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6830 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6835 klass = klass->parent;
6841 * mono_class_get_field_token:
6842 * @field: the field we need the token of
6844 * Get the token of a field. Note that the tokesn is only valid for the image
6845 * the field was loaded from. Don't use this function for fields in dynamic types.
6847 * Returns: The token representing the field in the image it was loaded from.
6850 mono_class_get_field_token (MonoClassField *field)
6852 MonoClass *klass = field->parent;
6855 mono_class_setup_fields (klass);
6860 int first_field_idx = mono_class_get_first_field_idx (klass);
6861 int fcount = mono_class_get_field_count (klass);
6862 for (i = 0; i < fcount; ++i) {
6863 if (&klass->fields [i] == field) {
6864 int idx = first_field_idx + i + 1;
6866 if (klass->image->uncompressed_metadata)
6867 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
6868 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
6871 klass = klass->parent;
6874 g_assert_not_reached ();
6879 mono_field_get_index (MonoClassField *field)
6881 int index = field - field->parent->fields;
6882 g_assert (index >= 0 && index < mono_class_get_field_count (field->parent));
6888 * mono_class_get_field_default_value:
6890 * Return the default value of the field as a pointer into the metadata blob.
6893 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
6896 guint32 constant_cols [MONO_CONSTANT_SIZE];
6898 MonoClass *klass = field->parent;
6899 MonoFieldDefaultValue *def_values;
6901 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
6903 def_values = mono_class_get_field_def_values (klass);
6905 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
6907 mono_class_set_field_def_values (klass, def_values);
6910 field_index = mono_field_get_index (field);
6912 if (!def_values [field_index].data) {
6913 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
6917 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
6919 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
6920 def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
6921 mono_memory_barrier ();
6922 def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
6925 *def_type = def_values [field_index].def_type;
6926 return def_values [field_index].data;
6930 mono_property_get_index (MonoProperty *prop)
6932 MonoClassPropertyInfo *info = mono_class_get_property_info (prop->parent);
6933 int index = prop - info->properties;
6935 g_assert (index >= 0 && index < info->count);
6941 * mono_class_get_property_default_value:
6943 * Return the default value of the field as a pointer into the metadata blob.
6946 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
6949 guint32 constant_cols [MONO_CONSTANT_SIZE];
6950 MonoClass *klass = property->parent;
6952 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
6954 * We don't cache here because it is not used by C# so it's quite rare, but
6955 * we still do the lookup in klass->ext because that is where the data
6956 * is stored for dynamic assemblies.
6959 if (image_is_dynamic (klass->image)) {
6960 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
6961 int prop_index = mono_property_get_index (property);
6962 if (info->def_values && info->def_values [prop_index].data) {
6963 *def_type = info->def_values [prop_index].def_type;
6964 return info->def_values [prop_index].data;
6968 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
6972 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
6973 *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
6974 return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
6978 mono_class_get_event_token (MonoEvent *event)
6980 MonoClass *klass = event->parent;
6984 MonoClassEventInfo *info = mono_class_get_event_info (klass);
6986 for (i = 0; i < info->count; ++i) {
6987 if (&info->events [i] == event)
6988 return mono_metadata_make_token (MONO_TABLE_EVENT, info->first + i + 1);
6991 klass = klass->parent;
6994 g_assert_not_reached ();
6999 * mono_class_get_property_from_name:
7001 * @name: name of the property to lookup in the specified class
7003 * Use this method to lookup a property in a class
7004 * Returns: the MonoProperty with the given name, or NULL if the property
7005 * does not exist on the @klass.
7008 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7012 gpointer iter = NULL;
7013 while ((p = mono_class_get_properties (klass, &iter))) {
7014 if (! strcmp (name, p->name))
7017 klass = klass->parent;
7023 * mono_class_get_property_token:
7024 * @prop: MonoProperty to query
7026 * Returns: The ECMA token for the specified property.
7029 mono_class_get_property_token (MonoProperty *prop)
7031 MonoClass *klass = prop->parent;
7035 gpointer iter = NULL;
7036 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
7037 while ((p = mono_class_get_properties (klass, &iter))) {
7038 if (&info->properties [i] == prop)
7039 return mono_metadata_make_token (MONO_TABLE_PROPERTY, info->first + i + 1);
7043 klass = klass->parent;
7046 g_assert_not_reached ();
7051 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7053 const char *name, *nspace;
7054 if (image_is_dynamic (image))
7055 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7057 switch (type_token & 0xff000000){
7058 case MONO_TOKEN_TYPE_DEF: {
7059 guint32 cols [MONO_TYPEDEF_SIZE];
7060 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7061 guint tidx = mono_metadata_token_index (type_token);
7063 if (tidx > tt->rows)
7064 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7066 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7067 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7068 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7069 if (strlen (nspace) == 0)
7070 return g_strdup_printf ("%s", name);
7072 return g_strdup_printf ("%s.%s", nspace, name);
7075 case MONO_TOKEN_TYPE_REF: {
7077 guint32 cols [MONO_TYPEREF_SIZE];
7078 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7079 guint tidx = mono_metadata_token_index (type_token);
7082 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7084 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7085 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7086 mono_error_cleanup (&error);
7090 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7091 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7092 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7093 if (strlen (nspace) == 0)
7094 return g_strdup_printf ("%s", name);
7096 return g_strdup_printf ("%s.%s", nspace, name);
7099 case MONO_TOKEN_TYPE_SPEC:
7100 return g_strdup_printf ("Typespec 0x%08x", type_token);
7102 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7107 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7109 if (image_is_dynamic (image))
7110 return g_strdup_printf ("DynamicAssembly %s", image->name);
7112 switch (type_token & 0xff000000){
7113 case MONO_TOKEN_TYPE_DEF:
7114 if (image->assembly)
7115 return mono_stringify_assembly_name (&image->assembly->aname);
7116 else if (image->assembly_name)
7117 return g_strdup (image->assembly_name);
7118 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7119 case MONO_TOKEN_TYPE_REF: {
7121 MonoAssemblyName aname;
7122 guint32 cols [MONO_TYPEREF_SIZE];
7123 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7124 guint32 idx = mono_metadata_token_index (type_token);
7127 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7129 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7130 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7131 mono_error_cleanup (&error);
7134 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7136 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7137 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7138 case MONO_RESOLUTION_SCOPE_MODULE:
7140 return g_strdup ("");
7141 case MONO_RESOLUTION_SCOPE_MODULEREF:
7143 return g_strdup ("");
7144 case MONO_RESOLUTION_SCOPE_TYPEREF:
7146 return g_strdup ("");
7147 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7148 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7149 return mono_stringify_assembly_name (&aname);
7151 g_assert_not_reached ();
7155 case MONO_TOKEN_TYPE_SPEC:
7157 return g_strdup ("");
7159 g_assert_not_reached ();
7166 * mono_class_get_full:
7167 * @image: the image where the class resides
7168 * @type_token: the token for the class
7169 * @context: the generic context used to evaluate generic instantiations in
7170 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7172 * Returns: The MonoClass that represents @type_token in @image
7175 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7179 klass = mono_class_get_checked (image, type_token, &error);
7181 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7182 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7184 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7190 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7194 mono_error_init (error);
7195 klass = mono_class_get_checked (image, type_token, error);
7197 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7198 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7203 * mono_class_get_checked:
7204 * @image: the image where the class resides
7205 * @type_token: the token for the class
7206 * @error: error object to return any error
7208 * Returns: The MonoClass that represents @type_token in @image, or NULL on error.
7211 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7213 MonoClass *klass = NULL;
7215 mono_error_init (error);
7217 if (image_is_dynamic (image)) {
7218 int table = mono_metadata_token_table (type_token);
7220 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7221 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7224 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
7228 switch (type_token & 0xff000000){
7229 case MONO_TOKEN_TYPE_DEF:
7230 klass = mono_class_create_from_typedef (image, type_token, error);
7232 case MONO_TOKEN_TYPE_REF:
7233 klass = mono_class_from_typeref_checked (image, type_token, error);
7235 case MONO_TOKEN_TYPE_SPEC:
7236 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7239 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7243 /* Generic case, should be avoided for when a better error is possible. */
7244 if (!klass && mono_error_ok (error)) {
7245 char *name = mono_class_name_from_token (image, type_token);
7246 char *assembly = mono_assembly_name_from_token (image, type_token);
7247 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7255 * mono_type_get_checked:
7256 * @image: the image where the type resides
7257 * @type_token: the token for the type
7258 * @context: the generic context used to evaluate generic instantiations in
7259 * @error: Error handling context
7261 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7263 * Returns: The MonoType that represents @type_token in @image
7266 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7268 MonoType *type = NULL;
7269 gboolean inflated = FALSE;
7271 mono_error_init (error);
7273 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7274 if (image_is_dynamic (image)) {
7275 MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
7276 return_val_if_nok (error, NULL);
7277 return mono_class_get_type (klass);
7280 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7281 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7288 return mono_class_get_type (klass);
7291 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7298 MonoType *tmp = type;
7299 type = mono_class_get_type (mono_class_from_mono_type (type));
7300 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7301 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7302 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7304 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7306 if (type->type != tmp->type)
7309 mono_metadata_free_type (tmp);
7316 * @image: image where the class token will be looked up.
7317 * @type_token: a type token from the image
7319 * Returns the MonoClass with the given @type_token on the @image
7322 mono_class_get (MonoImage *image, guint32 type_token)
7324 return mono_class_get_full (image, type_token, NULL);
7328 * mono_image_init_name_cache:
7330 * Initializes the class name cache stored in image->name_cache.
7332 * LOCKING: Acquires the corresponding image lock.
7335 mono_image_init_name_cache (MonoImage *image)
7337 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7338 guint32 cols [MONO_TYPEDEF_SIZE];
7341 guint32 i, visib, nspace_index;
7342 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7344 if (image->name_cache)
7347 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7349 if (image_is_dynamic (image)) {
7350 mono_image_lock (image);
7351 if (image->name_cache) {
7352 /* Somebody initialized it before us */
7353 g_hash_table_destroy (the_name_cache);
7355 mono_atomic_store_release (&image->name_cache, the_name_cache);
7357 mono_image_unlock (image);
7361 /* Temporary hash table to avoid lookups in the nspace_table */
7362 name_cache2 = g_hash_table_new (NULL, NULL);
7364 for (i = 1; i <= t->rows; ++i) {
7365 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7366 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7368 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7369 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7371 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7373 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7374 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7376 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7377 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7378 if (!nspace_table) {
7379 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7380 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7381 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7384 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7387 /* Load type names from EXPORTEDTYPES table */
7389 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7390 guint32 cols [MONO_EXP_TYPE_SIZE];
7393 for (i = 0; i < t->rows; ++i) {
7394 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7396 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7397 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7401 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7402 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7404 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7405 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7406 if (!nspace_table) {
7407 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7408 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7409 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7412 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7416 g_hash_table_destroy (name_cache2);
7418 mono_image_lock (image);
7419 if (image->name_cache) {
7420 /* Somebody initialized it before us */
7421 g_hash_table_destroy (the_name_cache);
7423 mono_atomic_store_release (&image->name_cache, the_name_cache);
7425 mono_image_unlock (image);
7428 /*FIXME Only dynamic assemblies should allow this operation.*/
7430 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7431 const char *name, guint32 index)
7433 GHashTable *nspace_table;
7434 GHashTable *name_cache;
7437 mono_image_init_name_cache (image);
7438 mono_image_lock (image);
7440 name_cache = image->name_cache;
7441 if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7442 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7443 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7446 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7447 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7449 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7451 mono_image_unlock (image);
7460 find_nocase (gpointer key, gpointer value, gpointer user_data)
7462 char *name = (char*)key;
7463 FindUserData *data = (FindUserData*)user_data;
7465 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7466 data->value = value;
7470 * mono_class_from_name_case:
7471 * @image: The MonoImage where the type is looked up in
7472 * @name_space: the type namespace
7473 * @name: the type short name.
7474 * @deprecated: use the mono_class_from_name_case_checked variant instead.
7476 * Obtains a MonoClass with a given namespace and a given name which
7477 * is located in the given MonoImage. The namespace and name
7478 * lookups are case insensitive.
7481 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7484 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7485 mono_error_cleanup (&error);
7491 * mono_class_from_name_case:
7492 * @image: The MonoImage where the type is looked up in
7493 * @name_space: the type namespace
7494 * @name: the type short name.
7497 * Obtains a MonoClass with a given namespace and a given name which
7498 * is located in the given MonoImage. The namespace and name
7499 * lookups are case insensitive.
7501 * Returns: The MonoClass if the given namespace and name were found, or NULL if it
7502 * was not found. The @error object will contain information about the problem
7506 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7508 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7509 guint32 cols [MONO_TYPEDEF_SIZE];
7514 mono_error_init (error);
7516 if (image_is_dynamic (image)) {
7518 FindUserData user_data;
7520 mono_image_init_name_cache (image);
7521 mono_image_lock (image);
7523 user_data.key = name_space;
7524 user_data.value = NULL;
7525 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7527 if (user_data.value) {
7528 GHashTable *nspace_table = (GHashTable*)user_data.value;
7530 user_data.key = name;
7531 user_data.value = NULL;
7533 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7535 if (user_data.value)
7536 token = GPOINTER_TO_UINT (user_data.value);
7539 mono_image_unlock (image);
7542 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7548 /* add a cache if needed */
7549 for (i = 1; i <= t->rows; ++i) {
7550 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7551 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7553 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7554 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7556 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7558 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7559 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7560 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7561 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7567 return_nested_in (MonoClass *klass, char *nested)
7570 char *s = strchr (nested, '/');
7571 gpointer iter = NULL;
7578 while ((found = mono_class_get_nested_types (klass, &iter))) {
7579 if (strcmp (found->name, nested) == 0) {
7581 return return_nested_in (found, s);
7589 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7591 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7592 MonoImage *file_image;
7596 mono_error_init (error);
7599 * The EXPORTEDTYPES table only contains public types, so have to search the
7601 * Note: image->modules contains the contents of the MODULEREF table, while
7602 * the real module list is in the FILE table.
7604 for (i = 0; i < file_table->rows; i++) {
7605 guint32 cols [MONO_FILE_SIZE];
7606 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7607 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7610 file_image = mono_image_load_file_for_image_checked (image, i + 1, error);
7612 klass = mono_class_from_name_checked (file_image, name_space, name, error);
7613 if (klass || !is_ok (error))
7622 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7624 GHashTable *nspace_table;
7625 MonoImage *loaded_image;
7632 mono_error_init (error);
7634 // Checking visited images avoids stack overflows when cyclic references exist.
7635 if (g_hash_table_lookup (visited_images, image))
7638 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7640 if ((nested = strchr (name, '/'))) {
7641 int pos = nested - name;
7642 int len = strlen (name);
7645 memcpy (buf, name, len + 1);
7647 nested = buf + pos + 1;
7651 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7652 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7653 gboolean res = get_class_from_name (image, name_space, name, &klass);
7656 klass = search_modules (image, name_space, name, error);
7661 return klass ? return_nested_in (klass, nested) : NULL;
7667 mono_image_init_name_cache (image);
7668 mono_image_lock (image);
7670 nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7673 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7675 mono_image_unlock (image);
7677 if (!token && image_is_dynamic (image) && image->modules) {
7678 /* Search modules as well */
7679 for (i = 0; i < image->module_count; ++i) {
7680 MonoImage *module = image->modules [i];
7682 klass = mono_class_from_name_checked (module, name_space, name, error);
7683 if (klass || !is_ok (error))
7689 klass = search_modules (image, name_space, name, error);
7690 if (klass || !is_ok (error))
7695 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7696 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7697 guint32 cols [MONO_EXP_TYPE_SIZE];
7700 idx = mono_metadata_token_index (token);
7702 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7704 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7705 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7706 loaded_image = mono_assembly_load_module_checked (image->assembly, impl >> MONO_IMPLEMENTATION_BITS, error);
7709 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7711 return klass ? return_nested_in (klass, nested) : NULL;
7713 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7714 guint32 assembly_idx;
7716 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7718 mono_assembly_load_reference (image, assembly_idx - 1);
7719 g_assert (image->references [assembly_idx - 1]);
7720 if (image->references [assembly_idx - 1] == (gpointer)-1)
7722 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
7724 return klass ? return_nested_in (klass, nested) : NULL;
7727 g_assert_not_reached ();
7731 token = MONO_TOKEN_TYPE_DEF | token;
7733 klass = mono_class_get_checked (image, token, error);
7735 return return_nested_in (klass, nested);
7740 * mono_class_from_name_checked:
7741 * @image: The MonoImage where the type is looked up in
7742 * @name_space: the type namespace
7743 * @name: the type short name.
7745 * Obtains a MonoClass with a given namespace and a given name which
7746 * is located in the given MonoImage.
7748 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
7749 * set if the class was not found or it will return NULL and set the error if there was a loading error.
7752 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7755 GHashTable *visited_images;
7757 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7759 klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
7761 g_hash_table_destroy (visited_images);
7767 * mono_class_from_name:
7768 * @image: The MonoImage where the type is looked up in
7769 * @name_space: the type namespace
7770 * @name: the type short name.
7772 * Obtains a MonoClass with a given namespace and a given name which
7773 * is located in the given MonoImage.
7775 * To reference nested classes, use the "/" character as a separator.
7776 * For example use "Foo/Bar" to reference the class Bar that is nested
7777 * inside Foo, like this: "class Foo { class Bar {} }".
7780 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7785 klass = mono_class_from_name_checked (image, name_space, name, &error);
7786 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
7792 * mono_class_load_from_name:
7793 * @image: The MonoImage where the type is looked up in
7794 * @name_space: the type namespace
7795 * @name: the type short name.
7797 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
7798 * This function should be used by the runtime for critical types to which there's no way to recover but crash
7799 * If they are missing. Thing of System.Object or System.String.
7802 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
7807 klass = mono_class_from_name_checked (image, name_space, name, &error);
7809 g_error ("Runtime critical type %s.%s not found", name_space, name);
7810 if (!mono_error_ok (&error))
7811 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
7816 * mono_class_try_load_from_name:
7817 * @image: The MonoImage where the type is looked up in
7818 * @name_space: the type namespace
7819 * @name: the type short name.
7821 * This function tries to load a type, returning the class was found or NULL otherwise.
7822 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
7824 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
7825 * a type that we would otherwise assume to be available but was not due some error.
7829 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
7834 klass = mono_class_from_name_checked (image, name_space, name, &error);
7835 if (!mono_error_ok (&error))
7836 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
7842 * mono_class_is_subclass_of:
7843 * @klass: class to probe if it is a subclass of another one
7844 * @klassc: the class we suspect is the base class
7845 * @check_interfaces: whether we should perform interface checks
7847 * This method determines whether @klass is a subclass of @klassc.
7849 * If the @check_interfaces flag is set, then if @klassc is an interface
7850 * this method return TRUE if the @klass implements the interface or
7851 * if @klass is an interface, if one of its base classes is @klass.
7853 * If @check_interfaces is false then, then if @klass is not an interface
7854 * then it returns TRUE if the @klass is a subclass of @klassc.
7856 * if @klass is an interface and @klassc is System.Object, then this function
7861 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
7862 gboolean check_interfaces)
7864 /* FIXME test for interfaces with variant generic arguments */
7865 mono_class_init (klass);
7866 mono_class_init (klassc);
7868 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
7869 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
7871 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
7874 for (i = 0; i < klass->interface_count; i ++) {
7875 MonoClass *ic = klass->interfaces [i];
7880 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
7885 * MS.NET thinks interfaces are a subclass of Object, so we think it as
7888 if (klassc == mono_defaults.object_class)
7895 mono_type_is_generic_argument (MonoType *type)
7897 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
7901 mono_class_has_variant_generic_params (MonoClass *klass)
7904 MonoGenericContainer *container;
7906 if (!mono_class_is_ginst (klass))
7909 container = mono_class_get_generic_container (mono_class_get_generic_class (klass)->container_class);
7911 for (i = 0; i < container->type_argc; ++i)
7912 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
7919 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
7921 if (target == candidate)
7924 if (check_for_reference_conv &&
7925 mono_type_is_generic_argument (&target->byval_arg) &&
7926 mono_type_is_generic_argument (&candidate->byval_arg)) {
7927 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
7928 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
7930 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
7933 if (!mono_class_is_assignable_from (target, candidate))
7939 * @container the generic container from the GTD
7940 * @klass: the class to be assigned to
7941 * @oklass: the source class
7943 * Both @klass and @oklass must be instances of the same generic interface.
7945 * Returns: TRUE if @klass can be assigned to a @klass variable
7948 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
7951 MonoType **klass_argv, **oklass_argv;
7952 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7953 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
7955 if (klass == oklass)
7958 /*Viable candidates are instances of the same generic interface*/
7959 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7962 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
7963 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
7965 for (j = 0; j < container->type_argc; ++j) {
7966 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
7967 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
7969 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
7973 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
7974 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
7976 if (param1_class != param2_class) {
7977 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
7978 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
7980 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
7981 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
7991 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
7993 MonoGenericParam *gparam, *ogparam;
7994 MonoGenericParamInfo *tinfo, *cinfo;
7995 MonoClass **candidate_class;
7996 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
7999 if (target == candidate)
8001 if (target->byval_arg.type != candidate->byval_arg.type)
8004 gparam = target->byval_arg.data.generic_param;
8005 ogparam = candidate->byval_arg.data.generic_param;
8006 tinfo = mono_generic_param_info (gparam);
8007 cinfo = mono_generic_param_info (ogparam);
8009 class_constraint_satisfied = FALSE;
8010 valuetype_constraint_satisfied = FALSE;
8012 /*candidate must have a super set of target's special constraints*/
8013 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8014 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8016 if (cinfo->constraints) {
8017 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8018 MonoClass *cc = *candidate_class;
8020 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8021 class_constraint_satisfied = TRUE;
8022 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8023 valuetype_constraint_satisfied = TRUE;
8026 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8027 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8029 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8031 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8033 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8034 valuetype_constraint_satisfied)) {
8039 /*candidate type constraints must be a superset of target's*/
8040 if (tinfo->constraints) {
8041 MonoClass **target_class;
8042 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8043 MonoClass *tc = *target_class;
8046 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8047 * check it's constraints since it satisfy the constraint by itself.
8049 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8052 if (!cinfo->constraints)
8055 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8056 MonoClass *cc = *candidate_class;
8058 if (mono_class_is_assignable_from (tc, cc))
8062 * This happens when we have the following:
8064 * Bar<K> where K : IFace
8065 * Foo<T, U> where T : U where U : IFace
8067 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8070 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8071 if (mono_gparam_is_assignable_from (target, cc))
8075 if (!*candidate_class)
8080 /*candidate itself must have a constraint that satisfy target*/
8081 if (cinfo->constraints) {
8082 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8083 MonoClass *cc = *candidate_class;
8084 if (mono_class_is_assignable_from (target, cc))
8092 * mono_class_is_assignable_from:
8093 * @klass: the class to be assigned to
8094 * @oklass: the source class
8096 * Returns: TRUE if an instance of object oklass can be assigned to an
8097 * instance of object @klass
8100 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8103 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8105 mono_class_init (klass);
8107 if (!oklass->inited)
8108 mono_class_init (oklass);
8110 if (mono_class_has_failure (klass) || mono_class_has_failure (oklass))
8113 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8114 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8116 return mono_gparam_is_assignable_from (klass, oklass);
8119 if (MONO_CLASS_IS_INTERFACE (klass)) {
8120 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8121 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8122 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8126 for (i = 0; constraints [i]; ++i) {
8127 if (mono_class_is_assignable_from (klass, constraints [i]))
8135 /* interface_offsets might not be set for dynamic classes */
8136 if (mono_class_get_ref_info_handle (oklass) && !oklass->interface_bitmap) {
8138 * oklass might be a generic type parameter but they have
8139 * interface_offsets set.
8141 gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8142 if (!is_ok (&error)) {
8143 mono_error_cleanup (&error);
8148 if (!oklass->interface_bitmap)
8149 /* Happens with generic instances of not-yet created dynamic types */
8151 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8154 if (klass->is_array_special_interface && oklass->rank == 1) {
8155 //XXX we could offset this by having the cast target computed at JIT time
8156 //XXX we could go even further and emit a wrapper that would do the extra type check
8157 MonoClass *iface_klass = mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
8158 MonoClass *obj_klass = oklass->cast_class; //This gets us the cast class of element type of the array
8160 // 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
8161 // We can't apply it for ref types as this would go wrong with arrays - IList<byte[]> would have byte tested
8162 if (iface_klass->valuetype)
8163 iface_klass = iface_klass->cast_class;
8165 //array covariant casts only operates on scalar to scalar
8166 //This is so int[] can't be casted to IComparable<int>[]
8167 if (!(obj_klass->valuetype && !iface_klass->valuetype) && mono_class_is_assignable_from (iface_klass, obj_klass))
8171 if (mono_class_has_variant_generic_params (klass)) {
8173 mono_class_setup_interfaces (oklass, &error);
8174 if (!mono_error_ok (&error)) {
8175 mono_error_cleanup (&error);
8179 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8180 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8181 MonoClass *iface = oklass->interfaces_packed [i];
8183 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8188 } else if (klass->delegate) {
8189 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8191 }else if (klass->rank) {
8192 MonoClass *eclass, *eoclass;
8194 if (oklass->rank != klass->rank)
8197 /* vectors vs. one dimensional arrays */
8198 if (oklass->byval_arg.type != klass->byval_arg.type)
8201 eclass = klass->cast_class;
8202 eoclass = oklass->cast_class;
8205 * a is b does not imply a[] is b[] when a is a valuetype, and
8206 * b is a reference type.
8209 if (eoclass->valuetype) {
8210 if ((eclass == mono_defaults.enum_class) ||
8211 (eclass == mono_defaults.enum_class->parent) ||
8212 (eclass == mono_defaults.object_class))
8216 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8217 } else if (mono_class_is_nullable (klass)) {
8218 if (mono_class_is_nullable (oklass))
8219 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8221 return mono_class_is_assignable_from (klass->cast_class, oklass);
8222 } else if (klass == mono_defaults.object_class)
8225 return mono_class_has_parent (oklass, klass);
8228 /*Check if @oklass is variant compatible with @klass.*/
8230 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8233 MonoType **klass_argv, **oklass_argv;
8234 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8235 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8237 /*Viable candidates are instances of the same generic interface*/
8238 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8241 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8242 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8244 for (j = 0; j < container->type_argc; ++j) {
8245 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8246 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8248 if (param1_class->valuetype != param2_class->valuetype)
8252 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8253 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8255 if (param1_class != param2_class) {
8256 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8257 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8259 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8260 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8268 /*Check if @candidate implements the interface @target*/
8270 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8274 gboolean is_variant = mono_class_has_variant_generic_params (target);
8276 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8277 if (mono_class_is_variant_compatible_slow (target, candidate))
8282 if (candidate == target)
8285 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8286 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8287 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (candidate);
8289 if (tb && tb->interfaces) {
8290 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8291 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8292 MonoClass *iface_class;
8294 /* we can't realize the type here since it can do pretty much anything. */
8297 iface_class = mono_class_from_mono_type (iface->type);
8298 if (iface_class == target)
8300 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8302 if (mono_class_implement_interface_slow (target, iface_class))
8307 /*setup_interfaces don't mono_class_init anything*/
8308 /*FIXME this doesn't handle primitive type arrays.
8309 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8310 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8312 mono_class_setup_interfaces (candidate, &error);
8313 if (!mono_error_ok (&error)) {
8314 mono_error_cleanup (&error);
8318 for (i = 0; i < candidate->interface_count; ++i) {
8319 if (candidate->interfaces [i] == target)
8322 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8325 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8329 candidate = candidate->parent;
8330 } while (candidate);
8336 * Check if @oklass can be assigned to @klass.
8337 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8340 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8342 if (candidate == target)
8344 if (target == mono_defaults.object_class)
8347 if (mono_class_has_parent (candidate, target))
8350 /*If target is not an interface there is no need to check them.*/
8351 if (MONO_CLASS_IS_INTERFACE (target))
8352 return mono_class_implement_interface_slow (target, candidate);
8354 if (target->delegate && mono_class_has_variant_generic_params (target))
8355 return mono_class_is_variant_compatible (target, candidate, FALSE);
8358 MonoClass *eclass, *eoclass;
8360 if (target->rank != candidate->rank)
8363 /* vectors vs. one dimensional arrays */
8364 if (target->byval_arg.type != candidate->byval_arg.type)
8367 eclass = target->cast_class;
8368 eoclass = candidate->cast_class;
8371 * a is b does not imply a[] is b[] when a is a valuetype, and
8372 * b is a reference type.
8375 if (eoclass->valuetype) {
8376 if ((eclass == mono_defaults.enum_class) ||
8377 (eclass == mono_defaults.enum_class->parent) ||
8378 (eclass == mono_defaults.object_class))
8382 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8384 /*FIXME properly handle nullables */
8385 /*FIXME properly handle (M)VAR */
8390 * mono_class_get_cctor:
8391 * @klass: A MonoClass pointer
8393 * Returns: The static constructor of @klass if it exists, NULL otherwise.
8396 mono_class_get_cctor (MonoClass *klass)
8398 MonoCachedClassInfo cached_info;
8400 if (image_is_dynamic (klass->image)) {
8402 * has_cctor is not set for these classes because mono_class_init () is
8405 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8408 mono_class_init (klass);
8410 if (!klass->has_cctor)
8413 if (mono_class_is_ginst (klass) && !klass->methods)
8414 return mono_class_get_inflated_method (klass, mono_class_get_cctor (mono_class_get_generic_class (klass)->container_class));
8416 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8418 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8419 if (!mono_error_ok (&error))
8420 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8424 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8428 * mono_class_get_finalizer:
8429 * @klass: The MonoClass pointer
8431 * Returns: The finalizer method of @klass if it exists, NULL otherwise.
8434 mono_class_get_finalizer (MonoClass *klass)
8436 MonoCachedClassInfo cached_info;
8439 mono_class_init (klass);
8440 if (!mono_class_has_finalizer (klass))
8443 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8445 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8446 if (!mono_error_ok (&error))
8447 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8450 mono_class_setup_vtable (klass);
8451 return klass->vtable [finalize_slot];
8456 * mono_class_needs_cctor_run:
8457 * @klass: the MonoClass pointer
8458 * @caller: a MonoMethod describing the caller
8460 * Determines whenever the class has a static constructor and whenever it
8461 * needs to be called when executing CALLER.
8464 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8468 method = mono_class_get_cctor (klass);
8470 return (method == caller) ? FALSE : TRUE;
8476 * mono_class_array_element_size:
8479 * Returns: The number of bytes an element of type @klass
8480 * uses when stored into an array.
8483 mono_class_array_element_size (MonoClass *klass)
8485 MonoType *type = &klass->byval_arg;
8488 switch (type->type) {
8491 case MONO_TYPE_BOOLEAN:
8495 case MONO_TYPE_CHAR:
8504 case MONO_TYPE_CLASS:
8505 case MONO_TYPE_STRING:
8506 case MONO_TYPE_OBJECT:
8507 case MONO_TYPE_SZARRAY:
8508 case MONO_TYPE_ARRAY:
8509 return sizeof (gpointer);
8514 case MONO_TYPE_VALUETYPE:
8515 if (type->data.klass->enumtype) {
8516 type = mono_class_enum_basetype (type->data.klass);
8517 klass = klass->element_class;
8520 return mono_class_instance_size (klass) - sizeof (MonoObject);
8521 case MONO_TYPE_GENERICINST:
8522 type = &type->data.generic_class->container_class->byval_arg;
8525 case MONO_TYPE_MVAR: {
8528 return mono_type_size (type, &align);
8530 case MONO_TYPE_VOID:
8534 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8540 * mono_array_element_size:
8541 * @ac: pointer to a #MonoArrayClass
8543 * Returns: The size of single array element.
8546 mono_array_element_size (MonoClass *ac)
8548 g_assert (ac->rank);
8549 return ac->sizes.element_size;
8553 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8554 MonoGenericContext *context)
8557 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8558 g_assert (mono_error_ok (&error));
8563 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8564 MonoGenericContext *context, MonoError *error)
8566 mono_error_init (error);
8568 if (image_is_dynamic (image)) {
8569 MonoClass *tmp_handle_class;
8570 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
8572 mono_error_assert_ok (error);
8573 g_assert (tmp_handle_class);
8575 *handle_class = tmp_handle_class;
8577 if (tmp_handle_class == mono_defaults.typehandle_class)
8578 return &((MonoClass*)obj)->byval_arg;
8583 switch (token & 0xff000000) {
8584 case MONO_TOKEN_TYPE_DEF:
8585 case MONO_TOKEN_TYPE_REF:
8586 case MONO_TOKEN_TYPE_SPEC: {
8589 *handle_class = mono_defaults.typehandle_class;
8590 type = mono_type_get_checked (image, token, context, error);
8594 mono_class_init (mono_class_from_mono_type (type));
8595 /* We return a MonoType* as handle */
8598 case MONO_TOKEN_FIELD_DEF: {
8600 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8602 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8606 *handle_class = mono_defaults.fieldhandle_class;
8607 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8611 mono_class_init (klass);
8612 return mono_class_get_field (klass, token);
8614 case MONO_TOKEN_METHOD_DEF:
8615 case MONO_TOKEN_METHOD_SPEC: {
8617 meth = mono_get_method_checked (image, token, NULL, context, error);
8619 *handle_class = mono_defaults.methodhandle_class;
8625 case MONO_TOKEN_MEMBER_REF: {
8626 guint32 cols [MONO_MEMBERREF_SIZE];
8628 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8629 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8630 mono_metadata_decode_blob_size (sig, &sig);
8631 if (*sig == 0x6) { /* it's a field */
8633 MonoClassField *field;
8634 field = mono_field_from_token_checked (image, token, &klass, context, error);
8636 *handle_class = mono_defaults.fieldhandle_class;
8640 meth = mono_get_method_checked (image, token, NULL, context, error);
8642 *handle_class = mono_defaults.methodhandle_class;
8647 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8653 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
8655 MonoClass *handle_class;
8656 mono_error_init (error);
8657 return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
8661 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
8663 return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
8666 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8669 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8671 get_cached_class_info = func;
8675 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8677 if (!get_cached_class_info)
8680 return get_cached_class_info (klass, res);
8684 mono_install_get_class_from_name (MonoGetClassFromName func)
8686 get_class_from_name = func;
8690 * mono_class_get_image:
8692 * Use this method to get the `MonoImage*` where this class came from.
8694 * Returns: The image where this class is defined.
8697 mono_class_get_image (MonoClass *klass)
8699 return klass->image;
8703 * mono_class_get_element_class:
8704 * @klass: the MonoClass to act on
8706 * Use this function to get the element class of an array.
8708 * Returns: The element class of an array.
8711 mono_class_get_element_class (MonoClass *klass)
8713 return klass->element_class;
8717 * mono_class_is_valuetype:
8718 * @klass: the MonoClass to act on
8720 * Use this method to determine if the provided `MonoClass*` represents a value type,
8721 * or a reference type.
8723 * Returns: TRUE if the MonoClass represents a ValueType, FALSE if it represents a reference type.
8726 mono_class_is_valuetype (MonoClass *klass)
8728 return klass->valuetype;
8732 * mono_class_is_enum:
8733 * @klass: the MonoClass to act on
8735 * Use this function to determine if the provided `MonoClass*` represents an enumeration.
8737 * Returns: TRUE if the MonoClass represents an enumeration.
8740 mono_class_is_enum (MonoClass *klass)
8742 return klass->enumtype;
8746 * mono_class_enum_basetype:
8747 * @klass: the MonoClass to act on
8749 * Use this function to get the underlying type for an enumeration value.
8751 * Returns: The underlying type representation for an enumeration.
8754 mono_class_enum_basetype (MonoClass *klass)
8756 if (klass->element_class == klass)
8757 /* SRE or broken types */
8760 return &klass->element_class->byval_arg;
8764 * mono_class_get_parent
8765 * @klass: the MonoClass to act on
8767 * Returns: The parent class for this class.
8770 mono_class_get_parent (MonoClass *klass)
8772 return klass->parent;
8776 * mono_class_get_nesting_type:
8777 * @klass: the MonoClass to act on
8779 * Use this function to obtain the class that the provided `MonoClass*` is nested on.
8781 * If the return is NULL, this indicates that this class is not nested.
8783 * Returns: The container type where this type is nested or NULL if this type is not a nested type.
8786 mono_class_get_nesting_type (MonoClass *klass)
8788 return klass->nested_in;
8792 * mono_class_get_rank:
8793 * @klass: the MonoClass to act on
8795 * Returns: The rank for the array (the number of dimensions).
8798 mono_class_get_rank (MonoClass *klass)
8804 * mono_class_get_name
8805 * @klass: the MonoClass to act on
8807 * Returns: The name of the class.
8810 mono_class_get_name (MonoClass *klass)
8816 * mono_class_get_namespace:
8817 * @klass: the MonoClass to act on
8819 * Returns: The namespace of the class.
8822 mono_class_get_namespace (MonoClass *klass)
8824 return klass->name_space;
8828 * mono_class_get_type:
8829 * @klass: the MonoClass to act on
8831 * This method returns the internal Type representation for the class.
8833 * Returns: The MonoType from the class.
8836 mono_class_get_type (MonoClass *klass)
8838 return &klass->byval_arg;
8842 * mono_class_get_type_token:
8843 * @klass: the MonoClass to act on
8845 * This method returns type token for the class.
8847 * Returns: The type token for the class.
8850 mono_class_get_type_token (MonoClass *klass)
8852 return klass->type_token;
8856 * mono_class_get_byref_type:
8857 * @klass: the MonoClass to act on
8862 mono_class_get_byref_type (MonoClass *klass)
8864 return &klass->this_arg;
8868 * mono_class_num_fields:
8869 * @klass: the MonoClass to act on
8871 * Returns: The number of static and instance fields in the class.
8874 mono_class_num_fields (MonoClass *klass)
8876 return mono_class_get_field_count (klass);
8880 * mono_class_num_methods:
8881 * @klass: the MonoClass to act on
8883 * Returns: The number of methods in the class.
8886 mono_class_num_methods (MonoClass *klass)
8888 return mono_class_get_method_count (klass);
8892 * mono_class_num_properties
8893 * @klass: the MonoClass to act on
8895 * Returns: The number of properties in the class.
8898 mono_class_num_properties (MonoClass *klass)
8900 mono_class_setup_properties (klass);
8902 return mono_class_get_property_info (klass)->count;
8906 * mono_class_num_events:
8907 * @klass: the MonoClass to act on
8909 * Returns: The number of events in the class.
8912 mono_class_num_events (MonoClass *klass)
8914 mono_class_setup_events (klass);
8916 return mono_class_get_event_info (klass)->count;
8920 * mono_class_get_fields:
8921 * @klass: the MonoClass to act on
8923 * This routine is an iterator routine for retrieving the fields in a class.
8925 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8926 * iterate over all of the elements. When no more values are
8927 * available, the return value is NULL.
8929 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
8932 mono_class_get_fields (MonoClass* klass, gpointer *iter)
8934 MonoClassField* field;
8938 mono_class_setup_fields (klass);
8939 if (mono_class_has_failure (klass))
8941 /* start from the first */
8942 if (mono_class_get_field_count (klass)) {
8943 *iter = &klass->fields [0];
8944 return &klass->fields [0];
8950 field = (MonoClassField *)*iter;
8952 if (field < &klass->fields [mono_class_get_field_count (klass)]) {
8960 * mono_class_get_methods
8961 * @klass: the MonoClass to act on
8963 * This routine is an iterator routine for retrieving the fields in a class.
8965 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8966 * iterate over all of the elements. When no more values are
8967 * available, the return value is NULL.
8969 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
8972 mono_class_get_methods (MonoClass* klass, gpointer *iter)
8974 MonoMethod** method;
8978 mono_class_setup_methods (klass);
8981 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8982 * FIXME we should better report this error to the caller
8984 if (!klass->methods)
8986 /* start from the first */
8987 if (mono_class_get_method_count (klass)) {
8988 *iter = &klass->methods [0];
8989 return klass->methods [0];
8995 method = (MonoMethod **)*iter;
8997 if (method < &klass->methods [mono_class_get_method_count (klass)]) {
9005 * mono_class_get_virtual_methods:
9007 * Iterate over the virtual methods of KLASS.
9009 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9012 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9014 MonoMethod** method;
9017 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9019 mono_class_setup_methods (klass);
9021 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9022 * FIXME we should better report this error to the caller
9024 if (!klass->methods)
9026 /* start from the first */
9027 method = &klass->methods [0];
9029 method = (MonoMethod **)*iter;
9032 int mcount = mono_class_get_method_count (klass);
9033 while (method < &klass->methods [mcount]) {
9034 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9038 if (method < &klass->methods [mcount]) {
9045 /* Search directly in metadata to avoid calling setup_methods () */
9046 MonoMethod *res = NULL;
9052 start_index = GPOINTER_TO_UINT (*iter);
9055 int first_idx = mono_class_get_first_method_idx (klass);
9056 int mcount = mono_class_get_method_count (klass);
9057 for (i = start_index; i < mcount; ++i) {
9060 /* first_idx points into the methodptr table */
9061 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
9063 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9069 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9070 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9072 /* Add 1 here so the if (*iter) check fails */
9073 *iter = GUINT_TO_POINTER (i + 1);
9082 * mono_class_get_properties:
9083 * @klass: the MonoClass to act on
9085 * This routine is an iterator routine for retrieving the properties in a class.
9087 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9088 * iterate over all of the elements. When no more values are
9089 * available, the return value is NULL.
9091 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9094 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9096 MonoProperty* property;
9100 mono_class_setup_properties (klass);
9101 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
9102 /* start from the first */
9104 *iter = &info->properties [0];
9105 return (MonoProperty *)*iter;
9111 property = (MonoProperty *)*iter;
9113 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
9114 if (property < &info->properties [info->count]) {
9116 return (MonoProperty *)*iter;
9122 * mono_class_get_events:
9123 * @klass: the MonoClass to act on
9125 * This routine is an iterator routine for retrieving the properties in a class.
9127 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9128 * iterate over all of the elements. When no more values are
9129 * available, the return value is NULL.
9131 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9134 mono_class_get_events (MonoClass* klass, gpointer *iter)
9140 mono_class_setup_events (klass);
9141 MonoClassEventInfo *info = mono_class_get_event_info (klass);
9142 /* start from the first */
9144 *iter = &info->events [0];
9145 return (MonoEvent *)*iter;
9151 event = (MonoEvent *)*iter;
9153 MonoClassEventInfo *info = mono_class_get_event_info (klass);
9154 if (event < &info->events [info->count]) {
9156 return (MonoEvent *)*iter;
9162 * mono_class_get_interfaces
9163 * @klass: the MonoClass to act on
9165 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9167 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9168 * iterate over all of the elements. When no more values are
9169 * available, the return value is NULL.
9171 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9174 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9182 mono_class_init (klass);
9183 if (!klass->interfaces_inited) {
9184 mono_class_setup_interfaces (klass, &error);
9185 if (!mono_error_ok (&error)) {
9186 mono_error_cleanup (&error);
9190 /* start from the first */
9191 if (klass->interface_count) {
9192 *iter = &klass->interfaces [0];
9193 return klass->interfaces [0];
9199 iface = (MonoClass **)*iter;
9201 if (iface < &klass->interfaces [klass->interface_count]) {
9209 setup_nested_types (MonoClass *klass)
9212 GList *classes, *nested_classes, *l;
9215 if (klass->nested_classes_inited)
9218 if (!klass->type_token)
9219 klass->nested_classes_inited = TRUE;
9221 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9225 guint32 cols [MONO_NESTED_CLASS_SIZE];
9226 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9227 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9228 if (!mono_error_ok (&error)) {
9229 /*FIXME don't swallow the error message*/
9230 mono_error_cleanup (&error);
9232 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9236 classes = g_list_prepend (classes, nclass);
9238 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9241 nested_classes = NULL;
9242 for (l = classes; l; l = l->next)
9243 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9244 g_list_free (classes);
9246 mono_loader_lock ();
9247 if (!klass->nested_classes_inited) {
9248 mono_class_set_nested_classes_property (klass, nested_classes);
9249 mono_memory_barrier ();
9250 klass->nested_classes_inited = TRUE;
9252 mono_loader_unlock ();
9256 * mono_class_get_nested_types
9257 * @klass: the MonoClass to act on
9259 * This routine is an iterator routine for retrieving the nested types of a class.
9260 * This works only if @klass is non-generic, or a generic type definition.
9262 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9263 * iterate over all of the elements. When no more values are
9264 * available, the return value is NULL.
9266 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9269 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9275 if (!klass->nested_classes_inited)
9276 setup_nested_types (klass);
9279 GList *nested_classes = mono_class_get_nested_classes_property (klass);
9280 /* start from the first */
9281 if (nested_classes) {
9282 *iter = nested_classes;
9283 return (MonoClass *)nested_classes->data;
9285 /* no nested types */
9289 item = (GList *)*iter;
9293 return (MonoClass *)item->data;
9300 * mono_class_is_delegate
9301 * @klass: the MonoClass to act on
9303 * Returns: TRUE if the MonoClass represents a System.Delegate.
9306 mono_class_is_delegate (MonoClass *klass)
9308 return klass->delegate;
9312 * mono_class_implements_interface
9313 * @klass: The MonoClass to act on
9314 * @interface: The interface to check if @klass implements.
9316 * Returns: TRUE if @klass implements @interface.
9319 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9321 return mono_class_is_assignable_from (iface, klass);
9325 * mono_field_get_name:
9326 * @field: the MonoClassField to act on
9328 * Returns: The name of the field.
9331 mono_field_get_name (MonoClassField *field)
9337 * mono_field_get_type:
9338 * @field: the MonoClassField to act on
9340 * Returns: MonoType of the field.
9343 mono_field_get_type (MonoClassField *field)
9346 MonoType *type = mono_field_get_type_checked (field, &error);
9347 if (!mono_error_ok (&error)) {
9348 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9349 mono_error_cleanup (&error);
9356 * mono_field_get_type_checked:
9357 * @field: the MonoClassField to act on
9358 * @error: used to return any erro found while retrieving @field type
9360 * Returns: MonoType of the field.
9363 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9365 mono_error_init (error);
9367 mono_field_resolve_type (field, error);
9372 * mono_field_get_parent:
9373 * @field: the MonoClassField to act on
9375 * Returns: MonoClass where the field was defined.
9378 mono_field_get_parent (MonoClassField *field)
9380 return field->parent;
9384 * mono_field_get_flags;
9385 * @field: the MonoClassField to act on
9387 * The metadata flags for a field are encoded using the
9388 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9390 * Returns: The flags for the field.
9393 mono_field_get_flags (MonoClassField *field)
9396 return mono_field_resolve_flags (field);
9397 return field->type->attrs;
9401 * mono_field_get_offset:
9402 * @field: the MonoClassField to act on
9404 * Returns: The field offset.
9407 mono_field_get_offset (MonoClassField *field)
9409 return field->offset;
9413 mono_field_get_rva (MonoClassField *field)
9417 MonoClass *klass = field->parent;
9418 MonoFieldDefaultValue *def_values;
9420 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9422 def_values = mono_class_get_field_def_values (klass);
9424 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
9426 mono_class_set_field_def_values (klass, def_values);
9429 field_index = mono_field_get_index (field);
9431 if (!def_values [field_index].data && !image_is_dynamic (klass->image)) {
9432 int first_field_idx = mono_class_get_first_field_idx (klass);
9433 mono_metadata_field_info (field->parent->image, first_field_idx + field_index, NULL, &rva, NULL);
9435 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9436 def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9439 return def_values [field_index].data;
9443 * mono_field_get_data:
9444 * @field: the MonoClassField to act on
9446 * Returns: A pointer to the metadata constant value or to the field
9447 * data if it has an RVA flag.
9450 mono_field_get_data (MonoClassField *field)
9452 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9453 MonoTypeEnum def_type;
9455 return mono_class_get_field_default_value (field, &def_type);
9456 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9457 return mono_field_get_rva (field);
9464 * mono_property_get_name:
9465 * @prop: the MonoProperty to act on
9467 * Returns: The name of the property
9470 mono_property_get_name (MonoProperty *prop)
9476 * mono_property_get_set_method
9477 * @prop: the MonoProperty to act on.
9479 * Returns: The setter method of the property (A MonoMethod)
9482 mono_property_get_set_method (MonoProperty *prop)
9488 * mono_property_get_get_method
9489 * @prop: the MonoProperty to act on.
9491 * Returns: The setter method of the property (A MonoMethod)
9494 mono_property_get_get_method (MonoProperty *prop)
9500 * mono_property_get_parent:
9501 * @prop: the MonoProperty to act on.
9503 * Returns: The MonoClass where the property was defined.
9506 mono_property_get_parent (MonoProperty *prop)
9508 return prop->parent;
9512 * mono_property_get_flags:
9513 * @prop: the MonoProperty to act on.
9515 * The metadata flags for a property are encoded using the
9516 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9518 * Returns: The flags for the property.
9521 mono_property_get_flags (MonoProperty *prop)
9527 * mono_event_get_name:
9528 * @event: the MonoEvent to act on
9530 * Returns: The name of the event.
9533 mono_event_get_name (MonoEvent *event)
9539 * mono_event_get_add_method:
9540 * @event: The MonoEvent to act on.
9542 * Returns: The @add' method for the event (a MonoMethod).
9545 mono_event_get_add_method (MonoEvent *event)
9551 * mono_event_get_remove_method:
9552 * @event: The MonoEvent to act on.
9554 * Returns: The @remove method for the event (a MonoMethod).
9557 mono_event_get_remove_method (MonoEvent *event)
9559 return event->remove;
9563 * mono_event_get_raise_method:
9564 * @event: The MonoEvent to act on.
9566 * Returns: The @raise method for the event (a MonoMethod).
9569 mono_event_get_raise_method (MonoEvent *event)
9571 return event->raise;
9575 * mono_event_get_parent:
9576 * @event: the MonoEvent to act on.
9578 * Returns: The MonoClass where the event is defined.
9581 mono_event_get_parent (MonoEvent *event)
9583 return event->parent;
9587 * mono_event_get_flags
9588 * @event: the MonoEvent to act on.
9590 * The metadata flags for an event are encoded using the
9591 * EVENT_* constants. See the tabledefs.h file for details.
9593 * Returns: The flags for the event.
9596 mono_event_get_flags (MonoEvent *event)
9598 return event->attrs;
9602 * mono_class_get_method_from_name:
9603 * @klass: where to look for the method
9604 * @name: name of the method
9605 * @param_count: number of parameters. -1 for any number.
9607 * Obtains a MonoMethod with a given name and number of parameters.
9608 * It only works if there are no multiple signatures for any given method name.
9611 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9613 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9617 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9619 MonoMethod *res = NULL;
9622 /* Search directly in the metadata to avoid calling setup_methods () */
9623 int first_idx = mono_class_get_first_method_idx (klass);
9624 int mcount = mono_class_get_method_count (klass);
9625 for (i = 0; i < mcount; ++i) {
9627 guint32 cols [MONO_METHOD_SIZE];
9629 MonoMethodSignature *sig;
9631 /* first_idx points into the methodptr table */
9632 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, first_idx + i, cols, MONO_METHOD_SIZE);
9634 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9635 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9637 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9640 if (param_count == -1) {
9644 sig = mono_method_signature_checked (method, &error);
9646 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9649 if (sig->param_count == param_count) {
9660 * mono_class_get_method_from_name_flags:
9661 * @klass: where to look for the method
9662 * @name_space: name of the method
9663 * @param_count: number of parameters. -1 for any number.
9664 * @flags: flags which must be set in the method
9666 * Obtains a MonoMethod with a given name and number of parameters.
9667 * It only works if there are no multiple signatures for any given method name.
9670 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9672 MonoMethod *res = NULL;
9675 mono_class_init (klass);
9677 if (mono_class_is_ginst (klass) && !klass->methods) {
9678 res = mono_class_get_method_from_name_flags (mono_class_get_generic_class (klass)->container_class, name, param_count, flags);
9681 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9682 if (!mono_error_ok (&error))
9683 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9688 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9689 mono_class_setup_methods (klass);
9691 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9692 See mono/tests/array_load_exception.il
9693 FIXME we should better report this error to the caller
9695 if (!klass->methods)
9697 int mcount = mono_class_get_method_count (klass);
9698 for (i = 0; i < mcount; ++i) {
9699 MonoMethod *method = klass->methods [i];
9701 if (method->name[0] == name [0] &&
9702 !strcmp (name, method->name) &&
9703 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9704 ((method->flags & flags) == flags)) {
9711 res = find_method_in_metadata (klass, name, param_count, flags);
9718 * mono_class_set_failure:
9719 * @klass: class in which the failure was detected
9720 * @ex_type: the kind of exception/error to be thrown (later)
9721 * @ex_data: exception data (specific to each type of exception/error)
9723 * Keep a detected failure informations in the class for later processing.
9724 * Note that only the first failure is kept.
9726 * LOCKING: Acquires the loader lock.
9729 mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error)
9731 g_assert (boxed_error != NULL);
9733 if (mono_class_has_failure (klass))
9736 mono_loader_lock ();
9737 klass->has_failure = 1;
9738 mono_class_set_exception_data (klass, boxed_error);
9739 mono_loader_unlock ();
9745 mono_class_has_failure (const MonoClass *klass)
9747 g_assert (klass != NULL);
9748 return klass->has_failure != 0;
9753 * mono_class_set_type_load_failure:
9754 * @klass: class in which the failure was detected
9755 * @fmt: Printf-style error message string.
9757 * Collect detected failure informaion in the class for later processing.
9758 * The error is stored as a MonoErrorBoxed as with mono_error_set_type_load_class ()
9759 * Note that only the first failure is kept.
9761 * Returns FALSE if a failure was already set on the class, or TRUE otherwise.
9763 * LOCKING: Acquires the loader lock.
9766 mono_class_set_type_load_failure (MonoClass *klass, const char * fmt, ...)
9768 MonoError prepare_error;
9771 if (mono_class_has_failure (klass))
9774 mono_error_init (&prepare_error);
9776 va_start (args, fmt);
9777 mono_error_vset_type_load_class (&prepare_error, klass, fmt, args);
9780 MonoErrorBoxed *box = mono_error_box (&prepare_error, klass->image);
9781 mono_error_cleanup (&prepare_error);
9782 return mono_class_set_failure (klass, box);
9786 * mono_classes_init:
9788 * Initialize the resources used by this module.
9791 mono_classes_init (void)
9793 mono_os_mutex_init (&classes_mutex);
9795 mono_native_tls_alloc (&setup_fields_tls_id, NULL);
9796 mono_native_tls_alloc (&init_pending_tls_id, NULL);
9798 mono_counters_register ("MonoClassDef count",
9799 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_def_count);
9800 mono_counters_register ("MonoClassGtd count",
9801 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gtd_count);
9802 mono_counters_register ("MonoClassGenericInst count",
9803 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ginst_count);
9804 mono_counters_register ("MonoClassGenericParam count",
9805 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gparam_count);
9806 mono_counters_register ("MonoClassArray count",
9807 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_array_count);
9808 mono_counters_register ("MonoClassPointer count",
9809 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_pointer_count);
9810 mono_counters_register ("Inflated methods size",
9811 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9812 mono_counters_register ("Inflated classes size",
9813 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9814 mono_counters_register ("MonoClass size",
9815 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9819 * mono_classes_cleanup:
9821 * Free the resources used by this module.
9824 mono_classes_cleanup (void)
9826 mono_native_tls_free (setup_fields_tls_id);
9827 mono_native_tls_free (init_pending_tls_id);
9829 if (global_interface_bitset)
9830 mono_bitset_free (global_interface_bitset);
9831 global_interface_bitset = NULL;
9832 mono_os_mutex_destroy (&classes_mutex);
9836 * mono_class_get_exception_for_failure:
9837 * @klass: class in which the failure was detected
9839 * Return a constructed MonoException than the caller can then throw
9840 * using mono_raise_exception - or NULL if no failure is present (or
9841 * doesn't result in an exception).
9844 mono_class_get_exception_for_failure (MonoClass *klass)
9846 if (!mono_class_has_failure (klass))
9848 MonoError unboxed_error;
9849 mono_error_init (&unboxed_error);
9850 mono_error_set_for_class_failure (&unboxed_error, klass);
9851 return mono_error_convert_to_exception (&unboxed_error);
9855 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
9857 outer_klass = mono_class_get_generic_type_definition (outer_klass);
9858 inner_klass = mono_class_get_generic_type_definition (inner_klass);
9860 if (outer_klass == inner_klass)
9862 inner_klass = inner_klass->nested_in;
9863 } while (inner_klass);
9868 mono_class_get_generic_type_definition (MonoClass *klass)
9870 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
9871 return gklass ? gklass->container_class : klass;
9875 * Check if @klass is a subtype of @parent ignoring generic instantiations.
9877 * Generic instantiations are ignored for all super types of @klass.
9879 * Visibility checks ignoring generic instantiations.
9882 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
9885 klass = mono_class_get_generic_type_definition (klass);
9886 parent = mono_class_get_generic_type_definition (parent);
9887 mono_class_setup_supertypes (klass);
9889 for (i = 0; i < klass->idepth; ++i) {
9890 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
9896 * Subtype can only access parent members with family protection if the site object
9897 * is subclass of Subtype. For example:
9898 * class A { protected int x; }
9900 * void valid_access () {
9904 * void invalid_access () {
9911 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
9913 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
9916 if (context_klass == NULL)
9918 /*if access_klass is not member_klass context_klass must be type compat*/
9919 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
9925 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
9928 if (accessing == accessed)
9930 if (!accessed || !accessing)
9933 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
9934 * anywhere so untrusted friends are not safe to access platform's code internals */
9935 if (mono_security_core_clr_enabled ()) {
9936 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
9940 mono_assembly_load_friends (accessed);
9941 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
9942 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
9943 /* Be conservative with checks */
9946 if (strcmp (accessing->aname.name, friend_->name))
9948 if (friend_->public_key_token [0]) {
9949 if (!accessing->aname.public_key_token [0])
9951 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
9960 * If klass is a generic type or if it is derived from a generic type, return the
9961 * MonoClass of the generic definition
9962 * Returns NULL if not found
9965 get_generic_definition_class (MonoClass *klass)
9968 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
9969 if (gklass && gklass->container_class)
9970 return gklass->container_class;
9971 klass = klass->parent;
9977 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
9980 for (i = 0; i < ginst->type_argc; ++i) {
9981 MonoType *type = ginst->type_argv[i];
9982 switch (type->type) {
9983 case MONO_TYPE_SZARRAY:
9984 if (!can_access_type (access_klass, type->data.klass))
9987 case MONO_TYPE_ARRAY:
9988 if (!can_access_type (access_klass, type->data.array->eklass))
9992 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
9995 case MONO_TYPE_CLASS:
9996 case MONO_TYPE_VALUETYPE:
9997 case MONO_TYPE_GENERICINST:
9998 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10008 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10012 if (access_klass == member_klass)
10015 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10018 if (access_klass->element_class && !access_klass->enumtype)
10019 access_klass = access_klass->element_class;
10021 if (member_klass->element_class && !member_klass->enumtype)
10022 member_klass = member_klass->element_class;
10024 access_level = mono_class_get_flags (member_klass) & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10026 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10029 if (mono_class_is_ginst (member_klass) && !can_access_instantiation (access_klass, mono_class_get_generic_class (member_klass)->context.class_inst))
10032 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10035 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10038 /*Non nested type with nested visibility. We just fail it.*/
10039 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10042 switch (access_level) {
10043 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10044 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10046 case TYPE_ATTRIBUTE_PUBLIC:
10049 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10052 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10053 return is_nesting_type (member_klass, access_klass);
10055 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10056 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10058 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10059 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10061 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10062 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10063 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10065 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10066 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10067 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10072 /* FIXME: check visibility of type, too */
10074 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10076 MonoClass *member_generic_def;
10077 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10080 MonoGenericClass *access_gklass = mono_class_try_get_generic_class (access_klass);
10081 if (((access_gklass && access_gklass->container_class) ||
10082 mono_class_is_gtd (access_klass)) &&
10083 (member_generic_def = get_generic_definition_class (member_klass))) {
10084 MonoClass *access_container;
10086 if (mono_class_is_gtd (access_klass))
10087 access_container = access_klass;
10089 access_container = access_gklass->container_class;
10091 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10095 /* Partition I 8.5.3.2 */
10096 /* the access level values are the same for fields and methods */
10097 switch (access_level) {
10098 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10099 /* same compilation unit */
10100 return access_klass->image == member_klass->image;
10101 case FIELD_ATTRIBUTE_PRIVATE:
10102 return access_klass == member_klass;
10103 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10104 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10105 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10108 case FIELD_ATTRIBUTE_ASSEMBLY:
10109 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10110 case FIELD_ATTRIBUTE_FAMILY:
10111 if (is_valid_family_access (access_klass, member_klass, context_klass))
10114 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10115 if (is_valid_family_access (access_klass, member_klass, context_klass))
10117 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10118 case FIELD_ATTRIBUTE_PUBLIC:
10125 * mono_method_can_access_field:
10126 * @method: Method that will attempt to access the field
10127 * @field: the field to access
10129 * Used to determine if a method is allowed to access the specified field.
10131 * Returns: TRUE if the given @method is allowed to access the @field while following
10132 * the accessibility rules of the CLI.
10135 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10137 /* FIXME: check all overlapping fields */
10138 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10140 MonoClass *nested = method->klass->nested_in;
10142 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10145 nested = nested->nested_in;
10152 * mono_method_can_access_method:
10153 * @method: Method that will attempt to access the other method
10154 * @called: the method that we want to probe for accessibility.
10156 * Used to determine if the @method is allowed to access the specified @called method.
10158 * Returns: TRUE if the given @method is allowed to invoke the @called while following
10159 * the accessibility rules of the CLI.
10162 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10164 method = mono_method_get_method_definition (method);
10165 called = mono_method_get_method_definition (called);
10166 return mono_method_can_access_method_full (method, called, NULL);
10170 * mono_method_can_access_method_full:
10171 * @method: The caller method
10172 * @called: The called method
10173 * @context_klass: The static type on stack of the owner @called object used
10175 * This function must be used with instance calls, as they have more strict family accessibility.
10176 * It can be used with static methods, but context_klass should be NULL.
10178 * Returns: TRUE if caller have proper visibility and acessibility to @called
10181 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10183 /* Wrappers are except from access checks */
10184 if (method->wrapper_type != MONO_WRAPPER_NONE || called->wrapper_type != MONO_WRAPPER_NONE)
10187 MonoClass *access_class = method->klass;
10188 MonoClass *member_class = called->klass;
10189 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10191 MonoClass *nested = access_class->nested_in;
10193 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10196 nested = nested->nested_in;
10203 can = can_access_type (access_class, member_class);
10205 MonoClass *nested = access_class->nested_in;
10207 can = can_access_type (nested, member_class);
10210 nested = nested->nested_in;
10217 if (called->is_inflated) {
10218 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10219 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10228 * mono_method_can_access_field_full:
10229 * @method: The caller method
10230 * @field: The accessed field
10231 * @context_klass: The static type on stack of the owner @field object used
10233 * This function must be used with instance fields, as they have more strict family accessibility.
10234 * It can be used with static fields, but context_klass should be NULL.
10236 * Returns: TRUE if caller have proper visibility and acessibility to @field
10239 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10241 MonoClass *access_class = method->klass;
10242 MonoClass *member_class = field->parent;
10243 /* FIXME: check all overlapping fields */
10244 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10246 MonoClass *nested = access_class->nested_in;
10248 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10251 nested = nested->nested_in;
10258 can = can_access_type (access_class, member_class);
10260 MonoClass *nested = access_class->nested_in;
10262 can = can_access_type (nested, member_class);
10265 nested = nested->nested_in;
10275 * mono_class_can_access_class:
10276 * @source_class: The source class
10277 * @target_class: The accessed class
10279 * This function returns is @target_class is visible to @source_class
10281 * Returns: TRUE if source have proper visibility and acessibility to target
10284 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10286 return can_access_type (source_class, target_class);
10290 * mono_type_is_valid_enum_basetype:
10291 * @type: The MonoType to check
10293 * Returns: TRUE if the type can be used as the basetype of an enum
10295 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10296 switch (type->type) {
10299 case MONO_TYPE_BOOLEAN:
10302 case MONO_TYPE_CHAR:
10316 * mono_class_is_valid_enum:
10317 * @klass: An enum class to be validated
10319 * This method verify the required properties an enum should have.
10321 * Returns: TRUE if the informed enum class is valid
10323 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10324 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10325 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10328 mono_class_is_valid_enum (MonoClass *klass)
10330 MonoClassField * field;
10331 gpointer iter = NULL;
10332 gboolean found_base_field = FALSE;
10334 g_assert (klass->enumtype);
10335 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10336 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10340 if (!mono_class_is_auto_layout (klass))
10343 while ((field = mono_class_get_fields (klass, &iter))) {
10344 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10345 if (found_base_field)
10347 found_base_field = TRUE;
10348 if (!mono_type_is_valid_enum_basetype (field->type))
10353 if (!found_base_field)
10356 if (mono_class_get_method_count (klass) > 0)
10363 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10365 return gklass->context.class_inst == mono_class_get_generic_container (gklass->container_class)->context.class_inst;
10369 * mono_class_setup_interface_id:
10371 * Initializes MonoClass::interface_id if required.
10373 * LOCKING: Acquires the loader lock.
10376 mono_class_setup_interface_id (MonoClass *klass)
10378 mono_loader_lock ();
10379 if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10380 klass->interface_id = mono_get_unique_iid (klass);
10381 mono_loader_unlock ();
10385 * mono_class_setup_interfaces:
10387 * Initialize klass->interfaces/interfaces_count.
10388 * LOCKING: Acquires the loader lock.
10389 * This function can fail the type.
10392 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10394 int i, interface_count;
10395 MonoClass **interfaces;
10397 mono_error_init (error);
10399 if (klass->interfaces_inited)
10402 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10403 MonoType *args [1];
10405 /* generic IList, ICollection, IEnumerable */
10406 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10407 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10409 args [0] = &klass->element_class->byval_arg;
10410 interfaces [0] = mono_class_bind_generic_parameters (
10411 mono_defaults.generic_ilist_class, 1, args, FALSE);
10412 if (interface_count > 1)
10413 interfaces [1] = mono_class_bind_generic_parameters (
10414 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10415 } else if (mono_class_is_ginst (klass)) {
10416 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
10418 mono_class_setup_interfaces (gklass, error);
10419 if (!mono_error_ok (error)) {
10420 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10424 interface_count = gklass->interface_count;
10425 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10426 for (i = 0; i < interface_count; i++) {
10427 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (mono_class_get_generic_class (klass)), error);
10428 if (!mono_error_ok (error)) {
10429 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10434 interface_count = 0;
10438 mono_image_lock (klass->image);
10440 if (!klass->interfaces_inited) {
10441 klass->interface_count = interface_count;
10442 klass->interfaces = interfaces;
10444 mono_memory_barrier ();
10446 klass->interfaces_inited = TRUE;
10449 mono_image_unlock (klass->image);
10453 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10455 MonoClass *klass = field->parent;
10456 MonoImage *image = klass->image;
10457 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10459 int field_idx = field - klass->fields;
10461 mono_error_init (error);
10464 MonoClassField *gfield = >d->fields [field_idx];
10465 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10466 if (!mono_error_ok (error)) {
10467 char *full_name = mono_type_get_full_name (gtd);
10468 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));
10469 g_free (full_name);
10472 ftype = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10473 if (!mono_error_ok (error)) {
10474 char *full_name = mono_type_get_full_name (klass);
10475 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));
10476 g_free (full_name);
10480 guint32 cols [MONO_FIELD_SIZE];
10481 MonoGenericContainer *container = NULL;
10482 int idx = mono_class_get_first_field_idx (klass) + field_idx;
10484 /*FIXME, in theory we do not lazy load SRE fields*/
10485 g_assert (!image_is_dynamic (image));
10487 if (mono_class_is_gtd (klass)) {
10488 container = mono_class_get_generic_container (klass);
10490 container = mono_class_get_generic_container (gtd);
10491 g_assert (container);
10494 /* first_field_idx and idx points into the fieldptr table */
10495 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10497 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10498 char *full_name = mono_type_get_full_name (klass);
10499 mono_error_set_type_load_class (error, klass, "Could not verify field '%s:%s' signature", full_name, field->name);;
10500 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
10501 g_free (full_name);
10505 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10507 mono_metadata_decode_value (sig, &sig);
10508 /* FIELD signature == 0x06 */
10509 g_assert (*sig == 0x06);
10511 ftype = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10513 char *full_name = mono_type_get_full_name (klass);
10514 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));
10515 g_free (full_name);
10518 mono_memory_barrier ();
10519 field->type = ftype;
10523 mono_field_resolve_flags (MonoClassField *field)
10525 MonoClass *klass = field->parent;
10526 MonoImage *image = klass->image;
10527 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10528 int field_idx = field - klass->fields;
10532 MonoClassField *gfield = >d->fields [field_idx];
10533 return mono_field_get_flags (gfield);
10535 int idx = mono_class_get_first_field_idx (klass) + field_idx;
10537 /*FIXME, in theory we do not lazy load SRE fields*/
10538 g_assert (!image_is_dynamic (image));
10540 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10545 * mono_class_get_fields_lazy:
10546 * @klass: the MonoClass to act on
10548 * This routine is an iterator routine for retrieving the fields in a class.
10549 * Only minimal information about fields are loaded. Accessors must be used
10550 * for all MonoClassField returned.
10552 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10553 * iterate over all of the elements. When no more values are
10554 * available, the return value is NULL.
10556 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10559 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10561 MonoClassField* field;
10565 mono_class_setup_basic_field_info (klass);
10566 if (!klass->fields)
10568 /* start from the first */
10569 if (mono_class_get_field_count (klass)) {
10570 *iter = &klass->fields [0];
10571 return (MonoClassField *)*iter;
10577 field = (MonoClassField *)*iter;
10579 if (field < &klass->fields [mono_class_get_field_count (klass)]) {
10581 return (MonoClassField *)*iter;
10587 mono_class_full_name (MonoClass *klass)
10589 return mono_type_full_name (&klass->byval_arg);
10592 /* Declare all shared lazy type lookup functions */
10593 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, System.Runtime.InteropServices, SafeHandle)