2 * class.c: Class management for the Mono runtime
5 * Miguel de Icaza (miguel@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9 * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
10 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
20 #include <mono/metadata/image.h>
21 #include <mono/metadata/image-internals.h>
22 #include <mono/metadata/assembly.h>
23 #include <mono/metadata/assembly-internals.h>
24 #include <mono/metadata/metadata.h>
25 #include <mono/metadata/metadata-internals.h>
26 #include <mono/metadata/profiler-private.h>
27 #include <mono/metadata/tabledefs.h>
28 #include <mono/metadata/tokentype.h>
29 #include <mono/metadata/class-internals.h>
30 #include <mono/metadata/object.h>
31 #include <mono/metadata/appdomain.h>
32 #include <mono/metadata/mono-endian.h>
33 #include <mono/metadata/debug-helpers.h>
34 #include <mono/metadata/reflection.h>
35 #include <mono/metadata/exception.h>
36 #include <mono/metadata/security-manager.h>
37 #include <mono/metadata/security-core-clr.h>
38 #include <mono/metadata/attrdefs.h>
39 #include <mono/metadata/gc-internals.h>
40 #include <mono/metadata/verify-internals.h>
41 #include <mono/metadata/mono-debug.h>
42 #include <mono/utils/mono-counters.h>
43 #include <mono/utils/mono-string.h>
44 #include <mono/utils/mono-error-internals.h>
45 #include <mono/utils/mono-logger-internals.h>
46 #include <mono/utils/mono-memory-model.h>
47 #include <mono/utils/atomic.h>
48 #include <mono/utils/bsearch.h>
49 #include <mono/utils/checked-build.h>
53 gboolean mono_print_vtable = FALSE;
54 gboolean mono_align_small_structs = FALSE;
57 guint32 inflated_classes_size, inflated_methods_size;
58 guint32 classes_size, class_ext_size, class_ext_count;
59 guint32 class_def_count, class_gtd_count, class_ginst_count, class_gparam_count, class_array_count, class_pointer_count;
61 /* Low level lock which protects data structures in this module */
62 static mono_mutex_t classes_mutex;
64 /* Function supplied by the runtime to find classes by name using information from the AOT file */
65 static MonoGetClassFromName get_class_from_name = NULL;
67 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error);
68 static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
69 static gboolean can_access_type (MonoClass *access_klass, MonoClass *member_klass);
70 static MonoMethod* find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags);
71 static int generic_array_methods (MonoClass *klass);
72 static void setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos);
74 static MonoMethod* mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter);
75 static char* mono_assembly_name_from_token (MonoImage *image, guint32 type_token);
76 static void mono_field_resolve_type (MonoClassField *field, MonoError *error);
77 static guint32 mono_field_resolve_flags (MonoClassField *field);
78 static void mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup);
79 static void mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gklass);
81 static gboolean mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error);
82 static gpointer mono_class_get_exception_data (const MonoClass *klass);
86 We use gclass recording to allow recursive system f types to be referenced by a parent.
88 Given the following type hierarchy:
90 class TextBox : TextBoxBase<TextBox> {}
91 class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
92 class TextInput<T> : Input<T> where T: TextInput<T> {}
95 The runtime tries to load TextBoxBase<>.
96 To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
97 To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
98 To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
100 At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded
101 at this point, iow, both are registered in the type map and both and a NULL parent. This means
102 that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
104 To fix that what we do is to record all generic instantes created while resolving the parent of
105 any generic type definition and, after resolved, correct the parent field if needed.
108 static int record_gclass_instantiation;
109 static GSList *gclass_recorded_list;
110 typedef gboolean (*gclass_record_func) (MonoClass*, void*);
112 /* This TLS variable points to a GSList of classes which have setup_fields () executing */
113 static MonoNativeTlsKey setup_fields_tls_id;
115 static MonoNativeTlsKey init_pending_tls_id;
120 mono_locks_os_acquire (&classes_mutex, ClassesLock);
124 classes_unlock (void)
126 mono_locks_os_release (&classes_mutex, ClassesLock);
130 * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
133 enable_gclass_recording (void)
135 ++record_gclass_instantiation;
139 * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
142 disable_gclass_recording (gclass_record_func func, void *user_data)
144 GSList **head = &gclass_recorded_list;
146 g_assert (record_gclass_instantiation > 0);
147 --record_gclass_instantiation;
150 GSList *node = *head;
151 if (func ((MonoClass*)node->data, user_data)) {
153 g_slist_free_1 (node);
159 /* We automatically discard all recorded gclasses when disabled. */
160 if (!record_gclass_instantiation && gclass_recorded_list) {
161 g_slist_free (gclass_recorded_list);
162 gclass_recorded_list = NULL;
167 * mono_class_from_typeref:
168 * @image: a MonoImage
169 * @type_token: a TypeRef token
171 * Creates the MonoClass* structure representing the type defined by
172 * the typeref token valid inside @image.
173 * Returns: The MonoClass* representing the typeref token, NULL ifcould
177 mono_class_from_typeref (MonoImage *image, guint32 type_token)
180 MonoClass *klass = mono_class_from_typeref_checked (image, type_token, &error);
181 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
186 * mono_class_from_typeref_checked:
187 * @image: a MonoImage
188 * @type_token: a TypeRef token
189 * @error: error return code, if any.
191 * Creates the MonoClass* structure representing the type defined by
192 * the typeref token valid inside @image.
194 * Returns: The MonoClass* representing the typeref token, NULL if it could
195 * not be loaded with the @error value filled with the information about the
199 mono_class_from_typeref_checked (MonoImage *image, guint32 type_token, MonoError *error)
201 guint32 cols [MONO_TYPEREF_SIZE];
202 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
204 const char *name, *nspace;
205 MonoClass *res = NULL;
208 mono_error_init (error);
210 if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, error))
213 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
215 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
216 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
218 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
219 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
220 case MONO_RESOLUTION_SCOPE_MODULE:
222 LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
223 This is not the observed behavior of existing implementations.
224 The defacto behavior is that it's just a typedef in disguise.
226 /* a typedef in disguise */
227 res = mono_class_from_name_checked (image, nspace, name, error);
230 case MONO_RESOLUTION_SCOPE_MODULEREF:
231 module = mono_image_load_module_checked (image, idx, error);
233 res = mono_class_from_name_checked (module, nspace, name, error);
236 case MONO_RESOLUTION_SCOPE_TYPEREF: {
237 MonoClass *enclosing;
240 if (idx == mono_metadata_token_index (type_token)) {
241 mono_error_set_bad_image (error, image, "Image with self-referencing typeref token %08x.", type_token);
245 enclosing = mono_class_from_typeref_checked (image, MONO_TOKEN_TYPE_REF | idx, error);
246 return_val_if_nok (error, NULL);
248 if (enclosing->nested_classes_inited && enclosing->ext) {
249 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
250 for (tmp = enclosing->ext->nested_classes; tmp; tmp = tmp->next) {
251 res = (MonoClass *)tmp->data;
252 if (strcmp (res->name, name) == 0)
256 /* Don't call mono_class_init as we might've been called by it recursively */
257 int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
259 guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
260 guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
261 const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
263 if (strcmp (nname, name) == 0)
264 return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, error);
266 i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
269 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name);
272 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
276 if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) {
277 mono_error_set_bad_image (error, image, "Image with invalid assemblyref token %08x.", idx);
281 if (!image->references || !image->references [idx - 1])
282 mono_assembly_load_reference (image, idx - 1);
283 g_assert (image->references [idx - 1]);
285 /* If the assembly did not load, register this as a type load exception */
286 if (image->references [idx - 1] == REFERENCE_MISSING){
287 MonoAssemblyName aname;
290 mono_assembly_get_assemblyref (image, idx - 1, &aname);
291 human_name = mono_stringify_assembly_name (&aname);
292 mono_error_set_assembly_load_simple (error, human_name, image->assembly ? image->assembly->ref_only : FALSE);
296 res = mono_class_from_name_checked (image->references [idx - 1]->image, nspace, name, error);
299 /* Generic case, should be avoided for when a better error is possible. */
300 if (!res && mono_error_ok (error)) {
301 char *name = mono_class_name_from_token (image, type_token);
302 char *assembly = mono_assembly_name_from_token (image, type_token);
303 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
310 mono_image_memdup (MonoImage *image, void *data, guint size)
312 void *res = mono_image_alloc (image, size);
313 memcpy (res, data, size);
317 /* Copy everything mono_metadata_free_array free. */
319 mono_dup_array_type (MonoImage *image, MonoArrayType *a)
322 a = (MonoArrayType *)mono_image_memdup (image, a, sizeof (MonoArrayType));
324 a->sizes = (int *)mono_image_memdup (image, a->sizes, a->numsizes * sizeof (int));
326 a->lobounds = (int *)mono_image_memdup (image, a->lobounds, a->numlobounds * sizeof (int));
328 a = (MonoArrayType *)g_memdup (a, sizeof (MonoArrayType));
330 a->sizes = (int *)g_memdup (a->sizes, a->numsizes * sizeof (int));
332 a->lobounds = (int *)g_memdup (a->lobounds, a->numlobounds * sizeof (int));
337 /* Copy everything mono_metadata_free_method_signature free. */
339 mono_metadata_signature_deep_dup (MonoImage *image, MonoMethodSignature *sig)
343 sig = mono_metadata_signature_dup_full (image, sig);
345 sig->ret = mono_metadata_type_dup (image, sig->ret);
346 for (i = 0; i < sig->param_count; ++i)
347 sig->params [i] = mono_metadata_type_dup (image, sig->params [i]);
353 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
355 MonoAssembly *ta = klass->image->assembly;
358 name = mono_stringify_assembly_name (&ta->aname);
359 g_string_append_printf (str, ", %s", name);
364 mono_type_name_check_byref (MonoType *type, GString *str)
367 g_string_append_c (str, '&');
371 * mono_identifier_escape_type_name_chars:
372 * @str: a destination string
373 * @identifier: an IDENTIFIER in internal form
377 * The displayed form of the identifier is appended to str.
379 * The displayed form of an identifier has the characters ,+&*[]\
380 * that have special meaning in type names escaped with a preceeding
381 * backslash (\) character.
384 mono_identifier_escape_type_name_chars (GString* str, const char* identifier)
390 // reserve space for common case: there will be no escaped characters.
391 g_string_set_size(str, n + strlen(identifier));
392 g_string_set_size(str, n);
394 for (const char* s = identifier; *s != 0 ; s++) {
403 g_string_append_c (str, '\\');
404 g_string_append_c (str, *s);
407 g_string_append_c (str, *s);
415 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
416 MonoTypeNameFormat format)
420 switch (type->type) {
421 case MONO_TYPE_ARRAY: {
422 int i, rank = type->data.array->rank;
423 MonoTypeNameFormat nested_format;
425 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
426 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
428 mono_type_get_name_recurse (
429 &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
430 g_string_append_c (str, '[');
432 g_string_append_c (str, '*');
433 for (i = 1; i < rank; i++)
434 g_string_append_c (str, ',');
435 g_string_append_c (str, ']');
437 mono_type_name_check_byref (type, str);
439 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
440 _mono_type_get_assembly_name (type->data.array->eklass, str);
443 case MONO_TYPE_SZARRAY: {
444 MonoTypeNameFormat nested_format;
446 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
447 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
449 mono_type_get_name_recurse (
450 &type->data.klass->byval_arg, str, FALSE, nested_format);
451 g_string_append (str, "[]");
453 mono_type_name_check_byref (type, str);
455 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
456 _mono_type_get_assembly_name (type->data.klass, str);
459 case MONO_TYPE_PTR: {
460 MonoTypeNameFormat nested_format;
462 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
463 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
465 mono_type_get_name_recurse (
466 type->data.type, str, FALSE, nested_format);
467 g_string_append_c (str, '*');
469 mono_type_name_check_byref (type, str);
471 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
472 _mono_type_get_assembly_name (mono_class_from_mono_type (type->data.type), str);
477 if (!mono_generic_param_info (type->data.generic_param))
478 g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num);
480 g_string_append (str, mono_generic_param_info (type->data.generic_param)->name);
482 mono_type_name_check_byref (type, str);
486 klass = mono_class_from_mono_type (type);
487 if (klass->nested_in) {
488 mono_type_get_name_recurse (
489 &klass->nested_in->byval_arg, str, TRUE, format);
490 if (format == MONO_TYPE_NAME_FORMAT_IL)
491 g_string_append_c (str, '.');
493 g_string_append_c (str, '+');
494 } else if (*klass->name_space) {
495 if (format == MONO_TYPE_NAME_FORMAT_IL)
496 g_string_append (str, klass->name_space);
498 mono_identifier_escape_type_name_chars (str, klass->name_space);
499 g_string_append_c (str, '.');
501 if (format == MONO_TYPE_NAME_FORMAT_IL) {
502 char *s = strchr (klass->name, '`');
503 int len = s ? s - klass->name : strlen (klass->name);
504 g_string_append_len (str, klass->name, len);
506 mono_identifier_escape_type_name_chars (str, klass->name);
510 if (mono_class_is_ginst (klass)) {
511 MonoGenericClass *gclass = mono_class_get_generic_class (klass);
512 MonoGenericInst *inst = gclass->context.class_inst;
513 MonoTypeNameFormat nested_format;
516 nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
517 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
519 if (format == MONO_TYPE_NAME_FORMAT_IL)
520 g_string_append_c (str, '<');
522 g_string_append_c (str, '[');
523 for (i = 0; i < inst->type_argc; i++) {
524 MonoType *t = inst->type_argv [i];
527 g_string_append_c (str, ',');
528 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
529 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
530 g_string_append_c (str, '[');
531 mono_type_get_name_recurse (inst->type_argv [i], str, FALSE, nested_format);
532 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
533 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
534 g_string_append_c (str, ']');
536 if (format == MONO_TYPE_NAME_FORMAT_IL)
537 g_string_append_c (str, '>');
539 g_string_append_c (str, ']');
540 } else if (mono_class_is_gtd (klass) &&
541 (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
542 (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
545 if (format == MONO_TYPE_NAME_FORMAT_IL)
546 g_string_append_c (str, '<');
548 g_string_append_c (str, '[');
549 for (i = 0; i < mono_class_get_generic_container (klass)->type_argc; i++) {
551 g_string_append_c (str, ',');
552 g_string_append (str, mono_generic_container_get_param_info (mono_class_get_generic_container (klass), i)->name);
554 if (format == MONO_TYPE_NAME_FORMAT_IL)
555 g_string_append_c (str, '>');
557 g_string_append_c (str, ']');
560 mono_type_name_check_byref (type, str);
562 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
563 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
564 _mono_type_get_assembly_name (klass, str);
570 * mono_type_get_name_full:
572 * @format: the format for the return string.
575 * Returns: The string representation in a number of formats:
577 * if format is MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
578 * returned in the formatrequired by System.Reflection, this is the
579 * inverse of mono_reflection_parse_type ().
581 * if format is MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
582 * be used by the IL assembler.
584 * if format is MONO_TYPE_NAME_FORMAT_FULL_NAME
586 * if format is MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
589 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
593 result = g_string_new ("");
595 mono_type_get_name_recurse (type, result, FALSE, format);
597 return g_string_free (result, FALSE);
601 * mono_type_get_full_name:
604 * Returns: The string representation for type as required by System.Reflection.
605 * The inverse of mono_reflection_parse_type ().
608 mono_type_get_full_name (MonoClass *klass)
610 return mono_type_get_name_full (mono_class_get_type (klass), MONO_TYPE_NAME_FORMAT_REFLECTION);
614 * mono_type_get_name:
617 * Returns: The string representation for type as it would be represented in IL code.
620 mono_type_get_name (MonoType *type)
622 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
626 * mono_type_get_underlying_type:
629 * Returns: The MonoType for the underlying integer type if @type
630 * is an enum and byref is false, otherwise the type itself.
633 mono_type_get_underlying_type (MonoType *type)
635 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype && !type->byref)
636 return mono_class_enum_basetype (type->data.klass);
637 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype && !type->byref)
638 return mono_class_enum_basetype (type->data.generic_class->container_class);
643 * mono_class_is_open_constructed_type:
646 * Returns: TRUE if type represents a generics open constructed type.
647 * IOW, not all type parameters required for the instantiation have
648 * been provided or it's a generic type definition.
650 * An open constructed type means it's a non realizable type. Not to
651 * be mixed up with an abstract type - we can't cast or dispatch to
652 * an open type, for example.
655 mono_class_is_open_constructed_type (MonoType *t)
661 case MONO_TYPE_SZARRAY:
662 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
663 case MONO_TYPE_ARRAY:
664 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
666 return mono_class_is_open_constructed_type (t->data.type);
667 case MONO_TYPE_GENERICINST:
668 return t->data.generic_class->context.class_inst->is_open;
669 case MONO_TYPE_CLASS:
670 case MONO_TYPE_VALUETYPE:
671 return mono_class_is_gtd (t->data.klass);
678 This is a simple function to catch the most common bad instances of generic types.
679 Specially those that might lead to further failures in the runtime.
682 is_valid_generic_argument (MonoType *type)
684 switch (type->type) {
686 //case MONO_TYPE_TYPEDBYREF:
694 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
696 mono_error_init (error);
698 switch (type->type) {
699 case MONO_TYPE_MVAR: {
701 int num = mono_type_get_generic_param_num (type);
702 MonoGenericInst *inst = context->method_inst;
705 if (num >= inst->type_argc) {
706 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
707 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
708 num, info ? info->name : "", inst->type_argc);
712 if (!is_valid_generic_argument (inst->type_argv [num])) {
713 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
714 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
715 num, info ? info->name : "", inst->type_argv [num]->type);
719 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
720 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
721 * ->byref and ->attrs from @type are propagated to the returned type.
723 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
724 nt->byref = type->byref;
725 nt->attrs = type->attrs;
728 case MONO_TYPE_VAR: {
730 int num = mono_type_get_generic_param_num (type);
731 MonoGenericInst *inst = context->class_inst;
734 if (num >= inst->type_argc) {
735 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
736 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
737 num, info ? info->name : "", inst->type_argc);
740 if (!is_valid_generic_argument (inst->type_argv [num])) {
741 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
742 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
743 num, info ? info->name : "", inst->type_argv [num]->type);
746 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
747 nt->byref = type->byref;
748 nt->attrs = type->attrs;
751 case MONO_TYPE_SZARRAY: {
752 MonoClass *eclass = type->data.klass;
753 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
754 if (!inflated || !mono_error_ok (error))
756 nt = mono_metadata_type_dup (image, type);
757 nt->data.klass = mono_class_from_mono_type (inflated);
758 mono_metadata_free_type (inflated);
761 case MONO_TYPE_ARRAY: {
762 MonoClass *eclass = type->data.array->eklass;
763 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
764 if (!inflated || !mono_error_ok (error))
766 nt = mono_metadata_type_dup (image, type);
767 nt->data.array->eklass = mono_class_from_mono_type (inflated);
768 mono_metadata_free_type (inflated);
771 case MONO_TYPE_GENERICINST: {
772 MonoGenericClass *gclass = type->data.generic_class;
773 MonoGenericInst *inst;
775 if (!gclass->context.class_inst->is_open)
778 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
779 return_val_if_nok (error, NULL);
781 if (inst != gclass->context.class_inst)
782 gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
784 if (gclass == type->data.generic_class)
787 nt = mono_metadata_type_dup (image, type);
788 nt->data.generic_class = gclass;
791 case MONO_TYPE_CLASS:
792 case MONO_TYPE_VALUETYPE: {
793 MonoClass *klass = type->data.klass;
794 MonoGenericContainer *container = mono_class_try_get_generic_container (klass);
795 MonoGenericInst *inst;
796 MonoGenericClass *gclass = NULL;
802 /* We can't use context->class_inst directly, since it can have more elements */
803 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
804 return_val_if_nok (error, NULL);
806 if (inst == container->context.class_inst)
809 gclass = mono_metadata_lookup_generic_class (klass, inst, image_is_dynamic (klass->image));
811 nt = mono_metadata_type_dup (image, type);
812 nt->type = MONO_TYPE_GENERICINST;
813 nt->data.generic_class = gclass;
823 mono_generic_class_get_context (MonoGenericClass *gclass)
825 return &gclass->context;
829 mono_class_get_context (MonoClass *klass)
831 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
832 return gklass ? mono_generic_class_get_context (gklass) : NULL;
836 * mono_class_inflate_generic_type_with_mempool:
837 * @mempool: a mempool
839 * @context: a generics context
840 * @error: error context
842 * The same as mono_class_inflate_generic_type, but allocates the MonoType
843 * from mempool if it is non-NULL. If it is NULL, the MonoType is
844 * allocated on the heap and is owned by the caller.
845 * The returned type can potentially be the same as TYPE, so it should not be
846 * modified by the caller, and it should be freed using mono_metadata_free_type ().
849 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
851 MonoType *inflated = NULL;
852 mono_error_init (error);
855 inflated = inflate_generic_type (image, type, context, error);
856 return_val_if_nok (error, NULL);
859 MonoType *shared = mono_metadata_get_shared_type (type);
864 return mono_metadata_type_dup (image, type);
868 mono_stats.inflated_type_count++;
873 * mono_class_inflate_generic_type:
875 * @context: a generics context
877 * If @type is a generic type and @context is not NULL, instantiate it using the
878 * generics context @context.
880 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
881 * on the heap and is owned by the caller. Returns NULL on error.
883 * @deprecated Please use mono_class_inflate_generic_type_checked instead
886 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
890 result = mono_class_inflate_generic_type_checked (type, context, &error);
891 mono_error_cleanup (&error);
896 * mono_class_inflate_generic_type:
898 * @context: a generics context
899 * @error: error context to use
901 * If @type is a generic type and @context is not NULL, instantiate it using the
902 * generics context @context.
904 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
905 * on the heap and is owned by the caller.
908 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
910 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
914 * mono_class_inflate_generic_type_no_copy:
916 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
920 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
922 MonoType *inflated = NULL;
924 mono_error_init (error);
926 inflated = inflate_generic_type (image, type, context, error);
927 return_val_if_nok (error, NULL);
933 mono_stats.inflated_type_count++;
938 * mono_class_inflate_generic_class:
940 * Inflate the class @gklass with @context. Set @error on failure.
943 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
948 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
949 return_val_if_nok (error, NULL);
951 res = mono_class_from_mono_type (inflated);
952 mono_metadata_free_type (inflated);
957 static MonoGenericContext
958 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
960 MonoGenericInst *class_inst = NULL;
961 MonoGenericInst *method_inst = NULL;
962 MonoGenericContext res = { NULL, NULL };
964 mono_error_init (error);
966 if (context->class_inst) {
967 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
968 if (!mono_error_ok (error))
972 if (context->method_inst) {
973 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
974 if (!mono_error_ok (error))
978 res.class_inst = class_inst;
979 res.method_inst = method_inst;
985 * mono_class_inflate_generic_method:
986 * @method: a generic method
987 * @context: a generics context
989 * Instantiate the generic method @method using the generics context @context.
991 * Returns: The new instantiated method
994 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
996 return mono_class_inflate_generic_method_full (method, NULL, context);
1000 mono_class_inflate_generic_method_checked (MonoMethod *method, MonoGenericContext *context, MonoError *error)
1002 return mono_class_inflate_generic_method_full_checked (method, NULL, context, error);
1006 * mono_class_inflate_generic_method_full:
1008 * Instantiate method @method with the generic context @context.
1009 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
1010 * Use mono_method_signature () and mono_method_get_header () to get the correct values.
1013 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
1016 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
1017 if (!mono_error_ok (&error))
1018 /*FIXME do proper error handling - on this case, kill this function. */
1019 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
1025 * mono_class_inflate_generic_method_full_checked:
1026 * Same as mono_class_inflate_generic_method_full but return failure using @error.
1029 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
1032 MonoMethodInflated *iresult, *cached;
1033 MonoMethodSignature *sig;
1034 MonoGenericContext tmp_context;
1036 mono_error_init (error);
1038 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1039 while (method->is_inflated) {
1040 MonoGenericContext *method_context = mono_method_get_context (method);
1041 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1043 tmp_context = inflate_generic_context (method_context, context, error);
1044 return_val_if_nok (error, NULL);
1046 context = &tmp_context;
1048 if (mono_metadata_generic_context_equal (method_context, context))
1051 method = imethod->declaring;
1055 * A method only needs to be inflated if the context has argument for which it is
1058 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1059 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1062 if (!((method->is_generic && context->method_inst) ||
1063 (mono_class_is_gtd (method->klass) && context->class_inst)))
1066 iresult = g_new0 (MonoMethodInflated, 1);
1067 iresult->context = *context;
1068 iresult->declaring = method;
1070 if (!context->method_inst && method->is_generic)
1071 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1073 if (!context->class_inst) {
1074 g_assert (!mono_class_is_ginst (iresult->declaring->klass));
1075 if (mono_class_is_gtd (iresult->declaring->klass))
1076 iresult->context.class_inst = mono_class_get_generic_container (iresult->declaring->klass)->context.class_inst;
1078 /* This can happen with some callers like mono_object_get_virtual_method () */
1079 if (!mono_class_is_gtd (iresult->declaring->klass) && !mono_class_is_ginst (iresult->declaring->klass))
1080 iresult->context.class_inst = NULL;
1082 MonoImageSet *set = mono_metadata_get_image_set_for_method (iresult);
1085 mono_image_set_lock (set);
1086 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1087 mono_image_set_unlock (set);
1091 return (MonoMethod*)cached;
1094 mono_stats.inflated_method_count++;
1096 inflated_methods_size += sizeof (MonoMethodInflated);
1098 sig = mono_method_signature (method);
1100 char *name = mono_type_get_full_name (method->klass);
1101 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1107 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1109 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1112 result = (MonoMethod *) iresult;
1113 result->is_inflated = TRUE;
1114 result->is_generic = FALSE;
1115 result->sre_method = FALSE;
1116 result->signature = NULL;
1118 if (method->wrapper_type) {
1119 MonoMethodWrapper *mw = (MonoMethodWrapper*)method;
1120 MonoMethodWrapper *resw = (MonoMethodWrapper*)result;
1121 int len = GPOINTER_TO_INT (((void**)mw->method_data) [0]);
1123 resw->method_data = (void **)g_malloc (sizeof (gpointer) * (len + 1));
1124 memcpy (resw->method_data, mw->method_data, sizeof (gpointer) * (len + 1));
1127 if (iresult->context.method_inst) {
1128 /* Set the generic_container of the result to the generic_container of method */
1129 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1131 if (generic_container && iresult->context.method_inst == generic_container->context.method_inst) {
1132 result->is_generic = 1;
1133 mono_method_set_generic_container (result, generic_container);
1138 MonoGenericClass *gklass_hint = mono_class_try_get_generic_class (klass_hint);
1139 if (gklass_hint && (gklass_hint->container_class != method->klass || gklass_hint->context.class_inst != context->class_inst))
1143 if (mono_class_is_gtd (method->klass))
1144 result->klass = klass_hint;
1146 if (!result->klass) {
1147 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1148 if (!mono_error_ok (error))
1151 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1153 mono_metadata_free_type (inflated);
1157 * FIXME: This should hold, but it doesn't:
1159 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1160 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1161 * g_assert (result->is_generic);
1164 * Fixing this here causes other things to break, hence a very
1165 * ugly hack in mini-trampolines.c - see
1166 * is_generic_method_definition().
1170 mono_image_set_lock (set);
1171 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1173 g_hash_table_insert (set->gmethod_cache, iresult, iresult);
1174 iresult->owner = set;
1177 mono_image_set_unlock (set);
1179 return (MonoMethod*)cached;
1187 * mono_get_inflated_method:
1189 * Obsolete. We keep it around since it's mentioned in the public API.
1192 mono_get_inflated_method (MonoMethod *method)
1198 * mono_method_get_context_general:
1200 * @uninflated: handle uninflated methods?
1202 * Returns the generic context of a method or NULL if it doesn't have
1203 * one. For an inflated method that's the context stored in the
1204 * method. Otherwise it's in the method's generic container or in the
1205 * generic container of the method's class.
1208 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1210 if (method->is_inflated) {
1211 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1212 return &imethod->context;
1216 if (method->is_generic)
1217 return &(mono_method_get_generic_container (method)->context);
1218 if (mono_class_is_gtd (method->klass))
1219 return &mono_class_get_generic_container (method->klass)->context;
1224 * mono_method_get_context:
1227 * Returns the generic context for method if it's inflated, otherwise
1231 mono_method_get_context (MonoMethod *method)
1233 return mono_method_get_context_general (method, FALSE);
1237 * mono_method_get_generic_container:
1239 * Returns the generic container of METHOD, which should be a generic method definition.
1240 * Returns NULL if METHOD is not a generic method definition.
1241 * LOCKING: Acquires the loader lock.
1243 MonoGenericContainer*
1244 mono_method_get_generic_container (MonoMethod *method)
1246 MonoGenericContainer *container;
1248 if (!method->is_generic)
1251 container = (MonoGenericContainer *)mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1252 g_assert (container);
1258 * mono_method_set_generic_container:
1260 * Sets the generic container of METHOD to CONTAINER.
1261 * LOCKING: Acquires the image lock.
1264 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1266 g_assert (method->is_generic);
1268 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1272 * mono_class_find_enum_basetype:
1273 * @class: The enum class
1275 * Determine the basetype of an enum by iterating through its fields. We do this
1276 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1279 mono_class_find_enum_basetype (MonoClass *klass, MonoError *error)
1281 MonoGenericContainer *container = NULL;
1282 MonoImage *m = klass->image;
1283 const int top = 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 = (MonoErrorBoxed*)mono_class_get_exception_data (klass);
1372 mono_error_set_from_boxed (oerror, box);
1379 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1383 mono_class_alloc (MonoClass *klass, int size)
1385 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
1387 return mono_image_set_alloc (gklass->owner, size);
1389 return mono_image_alloc (klass->image, size);
1393 mono_class_alloc0 (MonoClass *klass, int size)
1397 res = mono_class_alloc (klass, size);
1398 memset (res, 0, size);
1402 #define mono_class_new0(klass,struct_type, n_structs) \
1403 ((struct_type *) mono_class_alloc0 ((klass), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1406 * mono_class_setup_basic_field_info:
1407 * @class: The class to initialize
1409 * Initializes the following fields in MonoClass:
1410 * * klass->fields (only field->parent and field->name)
1411 * * klass->field.count
1412 * * klass->first_field_idx
1413 * LOCKING: Acquires the loader lock
1416 mono_class_setup_basic_field_info (MonoClass *klass)
1418 MonoGenericClass *gklass;
1419 MonoClassField *field;
1420 MonoClassField *fields;
1428 gklass = mono_class_try_get_generic_class (klass);
1429 gtd = gklass ? mono_class_get_generic_type_definition (klass) : NULL;
1430 image = klass->image;
1433 if (gklass && image_is_dynamic (gklass->container_class->image) && !gklass->container_class->wastypebuilder) {
1435 * This happens when a generic instance of an unfinished generic typebuilder
1436 * is used as an element type for creating an array type. We can't initialize
1437 * the fields of this class using the fields of gklass, since gklass is not
1438 * finished yet, fields could be added to it later.
1444 mono_class_setup_basic_field_info (gtd);
1446 mono_loader_lock ();
1447 mono_class_set_field_count (klass, mono_class_get_field_count (gtd));
1448 mono_loader_unlock ();
1451 top = mono_class_get_field_count (klass);
1453 fields = (MonoClassField *)mono_class_alloc0 (klass, sizeof (MonoClassField) * top);
1456 * Fetch all the field information.
1458 int first_field_idx = mono_class_has_static_metadata (klass) ? mono_class_get_first_field_idx (klass) : 0;
1459 for (i = 0; i < top; i++) {
1460 field = &fields [i];
1461 field->parent = klass;
1464 field->name = mono_field_get_name (>d->fields [i]);
1466 int idx = first_field_idx + i;
1467 /* first_field_idx and idx points into the fieldptr table */
1468 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1469 /* The name is needed for fieldrefs */
1470 field->name = mono_metadata_string_heap (image, name_idx);
1474 mono_memory_barrier ();
1476 mono_loader_lock ();
1478 klass->fields = fields;
1479 mono_loader_unlock ();
1483 * mono_class_set_failure_causedby_class:
1484 * @klass: the class that is failing
1485 * @caused_by: the class that caused the failure
1486 * @msg: Why @klass is failing.
1488 * If @caused_by has a failure, sets a TypeLoadException failure on
1489 * @klass with message "@msg, due to: {@caused_by message}".
1491 * Returns: TRUE if a failiure was set, or FALSE if @caused_by doesn't have a failure.
1494 mono_class_set_type_load_failure_causedby_class (MonoClass *klass, const MonoClass *caused_by, const gchar* msg)
1496 if (mono_class_has_failure (caused_by)) {
1497 MonoError cause_error;
1498 mono_error_init (&cause_error);
1499 mono_error_set_for_class_failure (&cause_error, caused_by);
1500 mono_class_set_type_load_failure (klass, "%s, due to: %s", msg, mono_error_get_message (&cause_error));
1501 mono_error_cleanup (&cause_error);
1510 * mono_class_setup_fields:
1511 * @klass: The class to initialize
1513 * Initializes klass->fields, computes class layout and sizes.
1514 * typebuilder_setup_fields () is the corresponding function for dynamic classes.
1515 * Sets the following fields in @klass:
1516 * - all the fields initialized by mono_class_init_sizes ()
1517 * - element_class/cast_class (for enums)
1518 * - field->type/offset for all fields
1521 * LOCKING: Acquires the loader lock.
1524 mono_class_setup_fields (MonoClass *klass)
1527 MonoImage *m = klass->image;
1529 guint32 layout = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK;
1531 guint32 real_size = 0;
1532 guint32 packing_size = 0;
1534 gboolean explicit_size;
1535 MonoClassField *field;
1536 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
1537 MonoClass *gtd = gklass ? mono_class_get_generic_type_definition (klass) : NULL;
1539 if (klass->fields_inited)
1542 if (gklass && image_is_dynamic (gklass->container_class->image) && !gklass->container_class->wastypebuilder) {
1544 * This happens when a generic instance of an unfinished generic typebuilder
1545 * is used as an element type for creating an array type. We can't initialize
1546 * the fields of this class using the fields of gklass, since gklass is not
1547 * finished yet, fields could be added to it later.
1552 mono_class_setup_basic_field_info (klass);
1553 top = mono_class_get_field_count (klass);
1556 mono_class_setup_fields (gtd);
1557 if (mono_class_set_type_load_failure_causedby_class (klass, gtd, "Generic type definition failed"))
1562 if (klass->parent) {
1563 /* For generic instances, klass->parent might not have been initialized */
1564 mono_class_init (klass->parent);
1565 mono_class_setup_fields (klass->parent);
1566 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Could not set up parent class"))
1568 instance_size = klass->parent->instance_size;
1570 instance_size = sizeof (MonoObject);
1573 /* Get the real size */
1574 explicit_size = mono_metadata_packing_from_typedef (klass->image, klass->type_token, &packing_size, &real_size);
1576 instance_size += real_size;
1579 * This function can recursively call itself.
1580 * Prevent infinite recursion by using a list in TLS.
1582 GSList *init_list = (GSList *)mono_native_tls_get_value (setup_fields_tls_id);
1583 if (g_slist_find (init_list, klass))
1585 init_list = g_slist_prepend (init_list, klass);
1586 mono_native_tls_set_value (setup_fields_tls_id, init_list);
1589 * Fetch all the field information.
1591 int first_field_idx = mono_class_has_static_metadata (klass) ? mono_class_get_first_field_idx (klass) : 0;
1592 for (i = 0; i < top; i++) {
1593 int idx = first_field_idx + i;
1594 field = &klass->fields [i];
1597 mono_field_resolve_type (field, &error);
1598 if (!mono_error_ok (&error)) {
1599 /*mono_field_resolve_type already failed class*/
1600 mono_error_cleanup (&error);
1604 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(klass), field->name);
1605 g_assert (field->type);
1608 if (mono_field_is_deleted (field))
1610 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1612 mono_metadata_field_info (m, idx, &uoffset, NULL, NULL);
1613 int offset = uoffset;
1615 if (offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1616 mono_class_set_type_load_failure (klass, "Missing field layout info for %s", field->name);
1619 if (offset < -1) { /*-1 is used to encode special static fields */
1620 mono_class_set_type_load_failure (klass, "Field '%s' has a negative offset %d", field->name, offset);
1623 if (mono_class_is_gtd (klass)) {
1624 mono_class_set_type_load_failure (klass, "Generic class cannot have explicit layout.");
1628 if (mono_type_has_exceptions (field->type)) {
1629 char *class_name = mono_type_get_full_name (klass);
1630 char *type_name = mono_type_full_name (field->type);
1632 mono_class_set_type_load_failure (klass, "");
1633 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1634 g_free (class_name);
1638 /* The def_value of fields is compute lazily during vtable creation */
1641 if (!mono_class_has_failure (klass))
1642 mono_class_layout_fields (klass, instance_size, packing_size, FALSE);
1644 init_list = g_slist_remove (init_list, klass);
1645 mono_native_tls_set_value (setup_fields_tls_id, init_list);
1649 init_sizes_with_info (MonoClass *klass, MonoCachedClassInfo *cached_info)
1652 klass->instance_size = cached_info->instance_size;
1653 klass->sizes.class_size = cached_info->class_size;
1654 klass->packing_size = cached_info->packing_size;
1655 klass->min_align = cached_info->min_align;
1656 klass->blittable = cached_info->blittable;
1657 klass->has_references = cached_info->has_references;
1658 klass->has_static_refs = cached_info->has_static_refs;
1659 klass->no_special_static_fields = cached_info->no_special_static_fields;
1662 if (!klass->size_inited)
1663 mono_class_setup_fields (klass);
1668 * mono_class_init_sizes:
1670 * Initializes the size related fields of @klass without loading all field data if possible.
1671 * Sets the following fields in @klass:
1673 * - sizes.class_size
1680 * Can fail the class.
1682 * LOCKING: Acquires the loader lock.
1685 mono_class_init_sizes (MonoClass *klass)
1687 MonoCachedClassInfo cached_info;
1688 gboolean has_cached_info;
1690 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
1692 init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
1696 * mono_type_get_basic_type_from_generic:
1699 * Returns a closed type corresponding to the possibly open type
1703 mono_type_get_basic_type_from_generic (MonoType *type)
1705 /* When we do generic sharing we let type variables stand for reference/primitive types. */
1706 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) &&
1707 (!type->data.generic_param->gshared_constraint || type->data.generic_param->gshared_constraint->type == MONO_TYPE_OBJECT))
1708 return &mono_defaults.object_class->byval_arg;
1713 class_has_references (MonoClass *klass)
1715 mono_class_init_sizes (klass);
1718 * has_references is not set if this is called recursively, but this is not a problem since this is only used
1719 * during field layout, and instance fields are initialized before static fields, and instance fields can't
1722 return klass->has_references;
1726 type_has_references (MonoClass *klass, MonoType *ftype)
1728 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (klass, ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && class_has_references (mono_class_from_mono_type (ftype)))))
1730 if (!ftype->byref && (ftype->type == MONO_TYPE_VAR || ftype->type == MONO_TYPE_MVAR)) {
1731 MonoGenericParam *gparam = ftype->data.generic_param;
1733 if (gparam->gshared_constraint)
1734 return class_has_references (mono_class_from_mono_type (gparam->gshared_constraint));
1740 * mono_class_layout_fields:
1742 * @base_instance_size: base instance size
1745 * This contains the common code for computing the layout of classes and sizes.
1746 * This should only be called from mono_class_setup_fields () and
1747 * typebuilder_setup_fields ().
1749 * LOCKING: Acquires the loader lock
1752 mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_size, gboolean sre)
1755 const int top = mono_class_get_field_count (klass);
1756 guint32 layout = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK;
1757 guint32 pass, passes, real_size;
1758 gboolean gc_aware_layout = FALSE;
1759 gboolean has_static_fields = FALSE;
1760 gboolean has_references = FALSE;
1761 gboolean has_static_refs = FALSE;
1762 MonoClassField *field;
1764 int instance_size = base_instance_size;
1765 int class_size, min_align;
1769 * We want to avoid doing complicated work inside locks, so we compute all the required
1770 * information and write it to @klass inside a lock.
1772 if (klass->fields_inited)
1775 if ((packing_size & 0xffffff00) != 0) {
1776 mono_class_set_type_load_failure (klass, "Could not load struct '%s' with packing size %d >= 256", klass->name, packing_size);
1780 if (klass->parent) {
1781 min_align = klass->parent->min_align;
1782 /* we use | since it may have been set already */
1783 has_references = klass->has_references | klass->parent->has_references;
1787 /* We can't really enable 16 bytes alignment until the GC supports it.
1788 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1789 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1790 Bug #506144 is an example of this issue.
1792 if (klass->simd_type)
1797 * When we do generic sharing we need to have layout
1798 * information for open generic classes (either with a generic
1799 * context containing type variables or with a generic
1800 * container), so we don't return in that case anymore.
1803 if (klass->enumtype) {
1804 for (i = 0; i < top; i++) {
1805 field = &klass->fields [i];
1806 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1807 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
1812 if (!mono_class_enum_basetype (klass)) {
1813 mono_class_set_type_load_failure (klass, "The enumeration's base type is invalid.");
1819 * Enable GC aware auto layout: in this mode, reference
1820 * fields are grouped together inside objects, increasing collector
1822 * Requires that all classes whose layout is known to native code be annotated
1823 * with [StructLayout (LayoutKind.Sequential)]
1824 * Value types have gc_aware_layout disabled by default, as per
1825 * what the default is for other runtimes.
1827 /* corlib is missing [StructLayout] directives in many places */
1828 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1829 if (!klass->valuetype)
1830 gc_aware_layout = TRUE;
1833 /* Compute klass->blittable */
1836 blittable = klass->parent->blittable;
1837 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(mono_is_corlib_image (klass->image) && !strcmp (klass->name_space, "System") && !strcmp (klass->name, "ValueType")) && top)
1839 for (i = 0; i < top; i++) {
1840 field = &klass->fields [i];
1842 if (mono_field_is_deleted (field))
1844 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1847 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1850 MonoClass *field_class = mono_class_from_mono_type (field->type);
1852 mono_class_setup_fields (field_class);
1853 if (mono_class_has_failure (field_class)) {
1854 MonoError field_error;
1855 mono_error_init (&field_error);
1856 mono_error_set_for_class_failure (&field_error, field_class);
1857 mono_class_set_type_load_failure (klass, "Could not set up field '%s' due to: %s", field->name, mono_error_get_message (&field_error));
1858 mono_error_cleanup (&field_error);
1862 if (!field_class || !field_class->blittable)
1866 if (klass->enumtype)
1867 blittable = klass->element_class->blittable;
1869 if (mono_class_has_failure (klass))
1871 if (klass == mono_defaults.string_class)
1874 /* Compute klass->has_references */
1876 * Process non-static fields first, since static fields might recursively
1877 * refer to the class itself.
1879 for (i = 0; i < top; i++) {
1882 field = &klass->fields [i];
1884 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1885 ftype = mono_type_get_underlying_type (field->type);
1886 ftype = mono_type_get_basic_type_from_generic (ftype);
1887 if (type_has_references (klass, ftype))
1888 has_references = TRUE;
1893 * Compute field layout and total size (not considering static fields)
1895 field_offsets = g_new0 (int, top);
1896 int first_field_idx = mono_class_has_static_metadata (klass) ? mono_class_get_first_field_idx (klass) : 0;
1898 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1899 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1900 if (gc_aware_layout)
1905 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1908 if (klass->parent) {
1909 mono_class_setup_fields (klass->parent);
1910 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Cannot initialize parent class"))
1912 real_size = klass->parent->instance_size;
1914 real_size = sizeof (MonoObject);
1917 for (pass = 0; pass < passes; ++pass) {
1918 for (i = 0; i < top; i++){
1923 field = &klass->fields [i];
1925 if (mono_field_is_deleted (field))
1927 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1930 ftype = mono_type_get_underlying_type (field->type);
1931 ftype = mono_type_get_basic_type_from_generic (ftype);
1932 if (gc_aware_layout) {
1933 if (type_has_references (klass, ftype)) {
1942 if ((top == 1) && (instance_size == sizeof (MonoObject)) &&
1943 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1944 /* This field is a hack inserted by MCS to empty structures */
1948 size = mono_type_size (field->type, &align);
1950 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1951 align = packing_size ? MIN (packing_size, align): align;
1952 /* if the field has managed references, we need to force-align it
1955 if (type_has_references (klass, ftype))
1956 align = MAX (align, sizeof (gpointer));
1958 min_align = MAX (align, min_align);
1959 field_offsets [i] = real_size;
1961 field_offsets [i] += align - 1;
1962 field_offsets [i] &= ~(align - 1);
1964 /*TypeBuilders produce all sort of weird things*/
1965 g_assert (image_is_dynamic (klass->image) || field_offsets [i] > 0);
1966 real_size = field_offsets [i] + size;
1969 instance_size = MAX (real_size, instance_size);
1971 if (instance_size & (min_align - 1)) {
1972 instance_size += min_align - 1;
1973 instance_size &= ~(min_align - 1);
1977 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
1981 for (i = 0; i < top; i++) {
1986 field = &klass->fields [i];
1989 * There must be info about all the fields in a type if it
1990 * uses explicit layout.
1992 if (mono_field_is_deleted (field))
1994 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1997 size = mono_type_size (field->type, &align);
1998 align = packing_size ? MIN (packing_size, align): align;
1999 min_align = MAX (align, min_align);
2002 /* Already set by typebuilder_setup_fields () */
2003 field_offsets [i] = field->offset + sizeof (MonoObject);
2005 int idx = first_field_idx + i;
2007 mono_metadata_field_info (klass->image, idx, &offset, NULL, NULL);
2008 field_offsets [i] = offset + sizeof (MonoObject);
2010 ftype = mono_type_get_underlying_type (field->type);
2011 ftype = mono_type_get_basic_type_from_generic (ftype);
2012 if (type_has_references (klass, ftype)) {
2013 if (field_offsets [i] % sizeof (gpointer)) {
2014 mono_class_set_type_load_failure (klass, "Reference typed field '%s' has explicit offset that is not pointer-size aligned.", field->name);
2021 real_size = MAX (real_size, size + field_offsets [i]);
2024 if (klass->has_references) {
2025 ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
2027 /* Check for overlapping reference and non-reference fields */
2028 for (i = 0; i < top; i++) {
2031 field = &klass->fields [i];
2033 if (mono_field_is_deleted (field))
2035 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2037 ftype = mono_type_get_underlying_type (field->type);
2038 if (MONO_TYPE_IS_REFERENCE (ftype))
2039 ref_bitmap [field_offsets [i] / sizeof (gpointer)] = 1;
2041 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)
2049 // FIXME: Too much code does this
2051 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field_offsets [i] / sizeof (gpointer)]) {
2052 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]);
2056 g_free (ref_bitmap);
2059 instance_size = MAX (real_size, instance_size);
2060 if (instance_size & (min_align - 1)) {
2061 instance_size += min_align - 1;
2062 instance_size &= ~(min_align - 1);
2068 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2070 * This leads to all kinds of problems with nested structs, so only
2071 * enable it when a MONO_DEBUG property is set.
2073 * For small structs, set min_align to at least the struct size to improve
2074 * performance, and since the JIT memset/memcpy code assumes this and generates
2075 * unaligned accesses otherwise. See #78990 for a testcase.
2077 if (mono_align_small_structs && top) {
2078 if (instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2079 min_align = MAX (min_align, instance_size - sizeof (MonoObject));
2083 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR)
2084 instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
2085 else if (klass->byval_arg.type == MONO_TYPE_PTR)
2086 instance_size = sizeof (MonoObject) + sizeof (gpointer);
2088 /* Publish the data */
2089 mono_loader_lock ();
2090 if (klass->instance_size && !klass->image->dynamic) {
2091 /* Might be already set using cached info */
2092 g_assert (klass->instance_size == instance_size);
2094 klass->instance_size = instance_size;
2096 klass->blittable = blittable;
2097 klass->has_references = has_references;
2098 klass->packing_size = packing_size;
2099 klass->min_align = min_align;
2100 for (i = 0; i < top; ++i) {
2101 field = &klass->fields [i];
2102 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
2103 klass->fields [i].offset = field_offsets [i];
2106 mono_memory_barrier ();
2107 klass->size_inited = 1;
2108 mono_loader_unlock ();
2111 * Compute static field layout and size
2112 * Static fields can reference the class itself, so this has to be
2113 * done after instance_size etc. are initialized.
2116 for (i = 0; i < top; i++) {
2120 field = &klass->fields [i];
2122 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2124 if (mono_field_is_deleted (field))
2127 if (mono_type_has_exceptions (field->type)) {
2128 mono_class_set_type_load_failure (klass, "Field '%s' has an invalid type.", field->name);
2132 has_static_fields = TRUE;
2134 size = mono_type_size (field->type, &align);
2135 field_offsets [i] = class_size;
2136 /*align is always non-zero here*/
2137 field_offsets [i] += align - 1;
2138 field_offsets [i] &= ~(align - 1);
2139 class_size = field_offsets [i] + size;
2142 if (has_static_fields && class_size == 0)
2143 /* Simplify code which depends on class_size != 0 if the class has static fields */
2146 /* Compute klass->has_static_refs */
2147 has_static_refs = FALSE;
2148 for (i = 0; i < top; i++) {
2151 field = &klass->fields [i];
2153 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
2154 ftype = mono_type_get_underlying_type (field->type);
2155 ftype = mono_type_get_basic_type_from_generic (ftype);
2156 if (type_has_references (klass, ftype))
2157 has_static_refs = TRUE;
2161 /*valuetypes can't be neither bigger than 1Mb or empty. */
2162 if (klass->valuetype && (klass->instance_size <= 0 || klass->instance_size > (0x100000 + sizeof (MonoObject))))
2163 mono_class_set_type_load_failure (klass, "Value type instance size (%d) cannot be zero, negative, or bigger than 1Mb", klass->instance_size);
2165 /* Publish the data */
2166 mono_loader_lock ();
2168 klass->sizes.class_size = class_size;
2169 klass->has_static_refs = has_static_refs;
2170 for (i = 0; i < top; ++i) {
2171 field = &klass->fields [i];
2173 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2174 field->offset = field_offsets [i];
2177 mono_memory_barrier ();
2178 klass->fields_inited = 1;
2179 mono_loader_unlock ();
2181 g_free (field_offsets);
2185 create_array_method (MonoClass *klass, const char *name, MonoMethodSignature *sig)
2189 method = (MonoMethod *) mono_image_alloc0 (klass->image, sizeof (MonoMethodPInvoke));
2190 method->klass = klass;
2191 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2192 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2193 method->signature = sig;
2194 method->name = name;
2197 if (name [0] == '.') {
2198 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2200 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2206 * mono_class_setup_methods:
2209 * Initializes the 'methods' array in CLASS.
2210 * Calling this method should be avoided if possible since it allocates a lot
2211 * of long-living MonoMethod structures.
2212 * Methods belonging to an interface are assigned a sequential slot starting
2215 * On failure this function sets klass->has_failure and stores a MonoErrorBoxed with details
2218 mono_class_setup_methods (MonoClass *klass)
2221 MonoMethod **methods;
2226 if (mono_class_is_ginst (klass)) {
2228 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2230 mono_class_init (gklass);
2231 if (!mono_class_has_failure (gklass))
2232 mono_class_setup_methods (gklass);
2233 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2236 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2237 count = mono_class_get_method_count (gklass);
2238 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * (count + 1));
2240 for (i = 0; i < count; i++) {
2241 methods [i] = mono_class_inflate_generic_method_full_checked (
2242 gklass->methods [i], klass, mono_class_get_context (klass), &error);
2243 if (!mono_error_ok (&error)) {
2244 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2245 mono_class_set_type_load_failure (klass, "Could not inflate method %s due to %s", method, mono_error_get_message (&error));
2248 mono_error_cleanup (&error);
2252 } else if (klass->rank) {
2254 MonoMethod *amethod;
2255 MonoMethodSignature *sig;
2256 int count_generic = 0, first_generic = 0;
2258 gboolean jagged_ctor = FALSE;
2260 count = 3 + (klass->rank > 1? 2: 1);
2262 mono_class_setup_interfaces (klass, &error);
2263 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2265 if (klass->rank == 1 && klass->element_class->rank) {
2270 if (klass->interface_count) {
2271 count_generic = generic_array_methods (klass);
2272 first_generic = count;
2273 count += klass->interface_count * count_generic;
2276 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * count);
2278 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2279 sig->ret = &mono_defaults.void_class->byval_arg;
2280 sig->pinvoke = TRUE;
2281 sig->hasthis = TRUE;
2282 for (i = 0; i < klass->rank; ++i)
2283 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2285 amethod = create_array_method (klass, ".ctor", sig);
2286 methods [method_num++] = amethod;
2287 if (klass->rank > 1) {
2288 sig = mono_metadata_signature_alloc (klass->image, klass->rank * 2);
2289 sig->ret = &mono_defaults.void_class->byval_arg;
2290 sig->pinvoke = TRUE;
2291 sig->hasthis = TRUE;
2292 for (i = 0; i < klass->rank * 2; ++i)
2293 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2295 amethod = create_array_method (klass, ".ctor", sig);
2296 methods [method_num++] = amethod;
2300 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2301 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2302 sig->ret = &mono_defaults.void_class->byval_arg;
2303 sig->pinvoke = TRUE;
2304 sig->hasthis = TRUE;
2305 for (i = 0; i < klass->rank + 1; ++i)
2306 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2307 amethod = create_array_method (klass, ".ctor", sig);
2308 methods [method_num++] = amethod;
2311 /* element Get (idx11, [idx2, ...]) */
2312 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2313 sig->ret = &klass->element_class->byval_arg;
2314 sig->pinvoke = TRUE;
2315 sig->hasthis = TRUE;
2316 for (i = 0; i < klass->rank; ++i)
2317 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2318 amethod = create_array_method (klass, "Get", sig);
2319 methods [method_num++] = amethod;
2320 /* element& Address (idx11, [idx2, ...]) */
2321 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2322 sig->ret = &klass->element_class->this_arg;
2323 sig->pinvoke = TRUE;
2324 sig->hasthis = TRUE;
2325 for (i = 0; i < klass->rank; ++i)
2326 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2327 amethod = create_array_method (klass, "Address", sig);
2328 methods [method_num++] = amethod;
2329 /* void Set (idx11, [idx2, ...], element) */
2330 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2331 sig->ret = &mono_defaults.void_class->byval_arg;
2332 sig->pinvoke = TRUE;
2333 sig->hasthis = TRUE;
2334 for (i = 0; i < klass->rank; ++i)
2335 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2336 sig->params [i] = &klass->element_class->byval_arg;
2337 amethod = create_array_method (klass, "Set", sig);
2338 methods [method_num++] = amethod;
2340 for (i = 0; i < klass->interface_count; i++)
2341 setup_generic_array_ifaces (klass, klass->interfaces [i], methods, first_generic + i * count_generic);
2342 } else if (mono_class_has_static_metadata (klass)) {
2344 int first_idx = mono_class_get_first_method_idx (klass);
2346 count = mono_class_get_method_count (klass);
2347 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * count);
2348 for (i = 0; i < count; ++i) {
2349 int idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_METHOD, first_idx + i + 1);
2350 methods [i] = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | idx, klass, NULL, &error);
2352 mono_class_set_type_load_failure (klass, "Could not load method %d due to %s", i, mono_error_get_message (&error));
2353 mono_error_cleanup (&error);
2357 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * 1);
2361 if (MONO_CLASS_IS_INTERFACE (klass)) {
2363 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2364 for (i = 0; i < count; ++i) {
2365 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2366 methods [i]->slot = slot++;
2370 mono_image_lock (klass->image);
2372 if (!klass->methods) {
2373 mono_class_set_method_count (klass, count);
2375 /* Needed because of the double-checking locking pattern */
2376 mono_memory_barrier ();
2378 klass->methods = methods;
2381 mono_image_unlock (klass->image);
2385 * mono_class_get_method_by_index:
2387 * Returns klass->methods [index], initializing klass->methods if neccesary.
2389 * LOCKING: Acquires the loader lock.
2392 mono_class_get_method_by_index (MonoClass *klass, int index)
2396 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
2397 /* Avoid calling setup_methods () if possible */
2398 if (gklass && !klass->methods) {
2401 m = mono_class_inflate_generic_method_full_checked (
2402 gklass->container_class->methods [index], klass, mono_class_get_context (klass), &error);
2403 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2405 * If setup_methods () is called later for this class, no duplicates are created,
2406 * since inflate_generic_method guarantees that only one instance of a method
2407 * is created for each context.
2410 mono_class_setup_methods (klass);
2411 g_assert (m == klass->methods [index]);
2415 mono_class_setup_methods (klass);
2416 if (mono_class_has_failure (klass)) /*FIXME do proper error handling*/
2418 g_assert (index >= 0 && index < mono_class_get_method_count (klass));
2419 return klass->methods [index];
2424 * mono_class_get_inflated_method:
2426 * Given an inflated class CLASS and a method METHOD which should be a method of
2427 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2430 mono_class_get_inflated_method (MonoClass *klass, MonoMethod *method)
2432 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2435 g_assert (method->klass == gklass);
2437 mono_class_setup_methods (gklass);
2438 g_assert (!mono_class_has_failure (gklass)); /*FIXME do proper error handling*/
2440 mcount = mono_class_get_method_count (gklass);
2441 for (i = 0; i < mcount; ++i) {
2442 if (gklass->methods [i] == method) {
2443 if (klass->methods) {
2444 return klass->methods [i];
2447 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], klass, mono_class_get_context (klass), &error);
2448 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2458 * mono_class_get_vtable_entry:
2460 * Returns klass->vtable [offset], computing it if neccesary. Returns NULL on failure.
2461 * LOCKING: Acquires the loader lock.
2464 mono_class_get_vtable_entry (MonoClass *klass, int offset)
2468 if (klass->rank == 1) {
2470 * szarrays do not overwrite any methods of Array, so we can avoid
2471 * initializing their vtables in some cases.
2473 mono_class_setup_vtable (klass->parent);
2474 if (offset < klass->parent->vtable_size)
2475 return klass->parent->vtable [offset];
2478 if (mono_class_is_ginst (klass)) {
2480 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2481 mono_class_setup_vtable (gklass);
2482 m = gklass->vtable [offset];
2484 m = mono_class_inflate_generic_method_full_checked (m, klass, mono_class_get_context (klass), &error);
2485 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2487 mono_class_setup_vtable (klass);
2488 if (mono_class_has_failure (klass))
2490 m = klass->vtable [offset];
2497 * mono_class_get_vtable_size:
2499 * Return the vtable size for KLASS.
2502 mono_class_get_vtable_size (MonoClass *klass)
2504 mono_class_setup_vtable (klass);
2506 return klass->vtable_size;
2510 * mono_class_setup_properties:
2512 * Initialize klass->ext.property and klass->ext.properties.
2514 * This method can fail the class.
2517 mono_class_setup_properties (MonoClass *klass)
2519 guint startm, endm, i, j;
2520 guint32 cols [MONO_PROPERTY_SIZE];
2521 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2522 MonoProperty *properties;
2526 if (klass->ext && klass->ext->properties)
2529 if (mono_class_is_ginst (klass)) {
2530 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2532 mono_class_init (gklass);
2533 mono_class_setup_properties (gklass);
2534 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2537 properties = mono_class_new0 (klass, MonoProperty, gklass->ext->property.count + 1);
2539 for (i = 0; i < gklass->ext->property.count; i++) {
2541 MonoProperty *prop = &properties [i];
2543 *prop = gklass->ext->properties [i];
2546 prop->get = mono_class_inflate_generic_method_full_checked (
2547 prop->get, klass, mono_class_get_context (klass), &error);
2549 prop->set = mono_class_inflate_generic_method_full_checked (
2550 prop->set, klass, mono_class_get_context (klass), &error);
2552 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2553 prop->parent = klass;
2556 first = gklass->ext->property.first;
2557 count = gklass->ext->property.count;
2559 first = mono_metadata_properties_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2560 count = last - first;
2563 mono_class_setup_methods (klass);
2564 if (mono_class_has_failure (klass))
2568 properties = (MonoProperty *)mono_class_alloc0 (klass, sizeof (MonoProperty) * count);
2569 for (i = first; i < last; ++i) {
2570 mono_metadata_decode_table_row (klass->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2571 properties [i - first].parent = klass;
2572 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2573 properties [i - first].name = mono_metadata_string_heap (klass->image, cols [MONO_PROPERTY_NAME]);
2575 startm = mono_metadata_methods_from_property (klass->image, i, &endm);
2576 int first_idx = mono_class_get_first_method_idx (klass);
2577 for (j = startm; j < endm; ++j) {
2580 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2582 if (klass->image->uncompressed_metadata) {
2584 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2585 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2586 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2588 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - first_idx];
2591 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2592 case METHOD_SEMANTIC_SETTER:
2593 properties [i - first].set = method;
2595 case METHOD_SEMANTIC_GETTER:
2596 properties [i - first].get = method;
2605 mono_class_alloc_ext (klass);
2607 mono_image_lock (klass->image);
2609 if (klass->ext->properties) {
2610 /* We leak 'properties' which was allocated from the image mempool */
2611 mono_image_unlock (klass->image);
2615 klass->ext->property.first = first;
2616 klass->ext->property.count = count;
2618 /* Flush any pending writes as we do double checked locking on klass->ext->properties */
2619 mono_memory_barrier ();
2621 /* Leave this assignment as the last op in the function */
2622 klass->ext->properties = properties;
2624 mono_image_unlock (klass->image);
2628 inflate_method_listz (MonoMethod **methods, MonoClass *klass, MonoGenericContext *context)
2630 MonoMethod **om, **retval;
2633 for (om = methods, count = 0; *om; ++om, ++count)
2636 retval = g_new0 (MonoMethod*, count + 1);
2638 for (om = methods, count = 0; *om; ++om, ++count) {
2640 retval [count] = mono_class_inflate_generic_method_full_checked (*om, klass, context, &error);
2641 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2647 /*This method can fail the class.*/
2649 mono_class_setup_events (MonoClass *klass)
2652 guint startm, endm, i, j;
2653 guint32 cols [MONO_EVENT_SIZE];
2654 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2658 if (klass->ext && klass->ext->events)
2661 if (mono_class_is_ginst (klass)) {
2662 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2663 MonoGenericContext *context = NULL;
2665 mono_class_setup_events (gklass);
2666 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2669 first = gklass->ext->event.first;
2670 count = gklass->ext->event.count;
2672 events = mono_class_new0 (klass, MonoEvent, count);
2675 context = mono_class_get_context (klass);
2677 for (i = 0; i < count; i++) {
2679 MonoEvent *event = &events [i];
2680 MonoEvent *gevent = &gklass->ext->events [i];
2682 mono_error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2684 event->parent = klass;
2685 event->name = gevent->name;
2686 event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, klass, context, &error) : NULL;
2687 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2688 event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, klass, context, &error) : NULL;
2689 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2690 event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, klass, context, &error) : NULL;
2691 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2693 #ifndef MONO_SMALL_CONFIG
2694 event->other = gevent->other ? inflate_method_listz (gevent->other, klass, context) : NULL;
2696 event->attrs = gevent->attrs;
2699 first = mono_metadata_events_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2700 count = last - first;
2703 mono_class_setup_methods (klass);
2704 if (mono_class_has_failure (klass)) {
2709 events = (MonoEvent *)mono_class_alloc0 (klass, sizeof (MonoEvent) * count);
2710 for (i = first; i < last; ++i) {
2711 MonoEvent *event = &events [i - first];
2713 mono_metadata_decode_table_row (klass->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2714 event->parent = klass;
2715 event->attrs = cols [MONO_EVENT_FLAGS];
2716 event->name = mono_metadata_string_heap (klass->image, cols [MONO_EVENT_NAME]);
2718 startm = mono_metadata_methods_from_event (klass->image, i, &endm);
2719 int first_idx = mono_class_get_first_method_idx (klass);
2720 for (j = startm; j < endm; ++j) {
2723 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2725 if (klass->image->uncompressed_metadata) {
2727 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2728 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2729 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2731 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - first_idx];
2734 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2735 case METHOD_SEMANTIC_ADD_ON:
2736 event->add = method;
2738 case METHOD_SEMANTIC_REMOVE_ON:
2739 event->remove = method;
2741 case METHOD_SEMANTIC_FIRE:
2742 event->raise = method;
2744 case METHOD_SEMANTIC_OTHER: {
2745 #ifndef MONO_SMALL_CONFIG
2748 if (event->other == NULL) {
2749 event->other = g_new0 (MonoMethod*, 2);
2751 while (event->other [n])
2753 event->other = (MonoMethod **)g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2755 event->other [n] = method;
2756 /* NULL terminated */
2757 event->other [n + 1] = NULL;
2768 mono_class_alloc_ext (klass);
2770 mono_image_lock (klass->image);
2772 if (klass->ext->events) {
2773 mono_image_unlock (klass->image);
2777 klass->ext->event.first = first;
2778 klass->ext->event.count = count;
2780 /* Flush any pending writes as we do double checked locking on klass->ext.events */
2781 mono_memory_barrier ();
2783 /* Leave this assignment as the last op in the function */
2784 klass->ext->events = events;
2786 mono_image_unlock (klass->image);
2790 * Global pool of interface IDs, represented as a bitset.
2791 * LOCKING: Protected by the classes lock.
2793 static MonoBitSet *global_interface_bitset = NULL;
2796 * mono_unload_interface_ids:
2797 * @bitset: bit set of interface IDs
2799 * When an image is unloaded, the interface IDs associated with
2800 * the image are put back in the global pool of IDs so the numbers
2804 mono_unload_interface_ids (MonoBitSet *bitset)
2807 mono_bitset_sub (global_interface_bitset, bitset);
2812 mono_unload_interface_id (MonoClass *klass)
2814 if (global_interface_bitset && klass->interface_id) {
2816 mono_bitset_clear (global_interface_bitset, klass->interface_id);
2822 * mono_get_unique_iid:
2825 * Assign a unique integer ID to the interface represented by @class.
2826 * The ID will positive and as small as possible.
2827 * LOCKING: Acquires the classes lock.
2828 * Returns: The new ID.
2831 mono_get_unique_iid (MonoClass *klass)
2835 g_assert (MONO_CLASS_IS_INTERFACE (klass));
2839 if (!global_interface_bitset) {
2840 global_interface_bitset = mono_bitset_new (128, 0);
2843 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2845 int old_size = mono_bitset_size (global_interface_bitset);
2846 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2847 mono_bitset_free (global_interface_bitset);
2848 global_interface_bitset = new_set;
2851 mono_bitset_set (global_interface_bitset, iid);
2852 /* set the bit also in the per-image set */
2853 if (!mono_class_is_ginst (klass)) {
2854 if (klass->image->interface_bitset) {
2855 if (iid >= mono_bitset_size (klass->image->interface_bitset)) {
2856 MonoBitSet *new_set = mono_bitset_clone (klass->image->interface_bitset, iid + 1);
2857 mono_bitset_free (klass->image->interface_bitset);
2858 klass->image->interface_bitset = new_set;
2861 klass->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2863 mono_bitset_set (klass->image->interface_bitset, iid);
2868 #ifndef MONO_SMALL_CONFIG
2869 if (mono_print_vtable) {
2871 char *type_name = mono_type_full_name (&klass->byval_arg);
2872 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
2873 if (gklass && !gklass->context.class_inst->is_open) {
2874 generic_id = gklass->context.class_inst->id;
2875 g_assert (generic_id != 0);
2879 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, klass->image->name, type_name, generic_id);
2884 /* I've confirmed iids safe past 16 bits, however bitset code uses a signed int while testing.
2885 * Once this changes, it should be safe for us to allow 2^32-1 interfaces, until then 2^31-2 is the max. */
2886 g_assert (iid < INT_MAX);
2891 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2896 mono_class_setup_interfaces (klass, error);
2897 return_if_nok (error);
2899 for (i = 0; i < klass->interface_count; i++) {
2900 ic = klass->interfaces [i];
2903 *res = g_ptr_array_new ();
2904 g_ptr_array_add (*res, ic);
2905 mono_class_init (ic);
2906 if (mono_class_has_failure (ic)) {
2907 mono_error_set_type_load_class (error, ic, "Error Loading class");
2911 collect_implemented_interfaces_aux (ic, res, error);
2912 return_if_nok (error);
2917 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2919 GPtrArray *res = NULL;
2921 collect_implemented_interfaces_aux (klass, &res, error);
2922 if (!mono_error_ok (error)) {
2924 g_ptr_array_free (res, TRUE);
2931 compare_interface_ids (const void *p_key, const void *p_element) {
2932 const MonoClass *key = (const MonoClass *)p_key;
2933 const MonoClass *element = *(const MonoClass **)p_element;
2935 return (key->interface_id - element->interface_id);
2938 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2940 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2941 MonoClass **result = (MonoClass **)mono_binary_search (
2943 klass->interfaces_packed,
2944 klass->interface_offsets_count,
2945 sizeof (MonoClass *),
2946 compare_interface_ids);
2948 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2955 * mono_class_interface_offset_with_variance:
2957 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2958 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2960 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2962 * FIXME figure out MS disambiguation rules and fix this function.
2965 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2966 int i = mono_class_interface_offset (klass, itf);
2967 *non_exact_match = FALSE;
2971 if (!mono_class_has_variant_generic_params (itf))
2974 for (i = 0; i < klass->interface_offsets_count; i++) {
2975 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2976 *non_exact_match = TRUE;
2977 return klass->interface_offsets_packed [i];
2985 print_implemented_interfaces (MonoClass *klass) {
2988 GPtrArray *ifaces = NULL;
2990 int ancestor_level = 0;
2992 name = mono_type_get_full_name (klass);
2993 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2996 for (i = 0; i < klass->interface_offsets_count; i++)
2997 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2998 klass->interfaces_packed [i]->interface_id,
2999 klass->interface_offsets_packed [i],
3000 mono_class_get_method_count (klass->interfaces_packed [i]),
3001 klass->interfaces_packed [i]->name_space,
3002 klass->interfaces_packed [i]->name );
3003 printf ("Interface flags: ");
3004 for (i = 0; i <= klass->max_interface_id; i++)
3005 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
3006 printf ("(%d,T)", i);
3008 printf ("(%d,F)", i);
3010 printf ("Dump interface flags:");
3011 #ifdef COMPRESSED_INTERFACE_BITMAP
3013 const uint8_t* p = klass->interface_bitmap;
3014 i = klass->max_interface_id;
3016 printf (" %d x 00 %02X", p [0], p [1]);
3022 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
3023 printf (" %02X", klass->interface_bitmap [i]);
3026 while (klass != NULL) {
3027 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
3028 ifaces = mono_class_get_implemented_interfaces (klass, &error);
3029 if (!mono_error_ok (&error)) {
3030 printf (" Type failed due to %s\n", mono_error_get_message (&error));
3031 mono_error_cleanup (&error);
3032 } else if (ifaces) {
3033 for (i = 0; i < ifaces->len; i++) {
3034 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3035 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
3036 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3038 mono_class_interface_offset (klass, ic),
3039 mono_class_get_method_count (ic),
3043 g_ptr_array_free (ifaces, TRUE);
3046 klass = klass->parent;
3051 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
3054 args [0] = &arg0->byval_arg;
3056 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
3060 array_class_get_if_rank (MonoClass *klass, guint rank)
3062 return rank ? mono_array_class_get (klass, rank) : klass;
3066 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
3068 valuetype_types [0] = eclass;
3069 if (eclass == mono_defaults.int16_class)
3070 valuetype_types [1] = mono_defaults.uint16_class;
3071 else if (eclass == mono_defaults.uint16_class)
3072 valuetype_types [1] = mono_defaults.int16_class;
3073 else if (eclass == mono_defaults.int32_class)
3074 valuetype_types [1] = mono_defaults.uint32_class;
3075 else if (eclass == mono_defaults.uint32_class)
3076 valuetype_types [1] = mono_defaults.int32_class;
3077 else if (eclass == mono_defaults.int64_class)
3078 valuetype_types [1] = mono_defaults.uint64_class;
3079 else if (eclass == mono_defaults.uint64_class)
3080 valuetype_types [1] = mono_defaults.int64_class;
3081 else if (eclass == mono_defaults.byte_class)
3082 valuetype_types [1] = mono_defaults.sbyte_class;
3083 else if (eclass == mono_defaults.sbyte_class)
3084 valuetype_types [1] = mono_defaults.byte_class;
3085 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
3086 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
3089 static GENERATE_GET_CLASS_WITH_CACHE (generic_icollection, System.Collections.Generic, ICollection`1)
3090 static GENERATE_GET_CLASS_WITH_CACHE (generic_ienumerable, System.Collections.Generic, IEnumerable`1)
3091 static GENERATE_GET_CLASS_WITH_CACHE (generic_ienumerator, System.Collections.Generic, IEnumerator`1)
3092 static GENERATE_GET_CLASS_WITH_CACHE (generic_ireadonlylist, System.Collections.Generic, IReadOnlyList`1)
3093 static GENERATE_GET_CLASS_WITH_CACHE (generic_ireadonlycollection, System.Collections.Generic, IReadOnlyCollection`1)
3095 /* this won't be needed once bug #325495 is completely fixed
3096 * though we'll need something similar to know which interfaces to allow
3097 * in arrays when they'll be lazyly created
3099 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
3100 * MS returns diferrent types based on which instance is called. For example:
3101 * object obj = new byte[10][];
3102 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
3103 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
3106 * Fixing this should kill quite some code, save some bits and improve compatibility.
3109 get_implicit_generic_array_interfaces (MonoClass *klass, int *num, int *is_enumerator)
3111 MonoClass *eclass = klass->element_class;
3112 MonoClass* generic_icollection_class;
3113 MonoClass* generic_ienumerable_class;
3114 MonoClass* generic_ienumerator_class;
3115 MonoClass* generic_ireadonlylist_class;
3116 MonoClass* generic_ireadonlycollection_class;
3117 MonoClass *valuetype_types[2] = { NULL, NULL };
3118 MonoClass **interfaces = NULL;
3119 int i, nifaces, interface_count, real_count, original_rank;
3121 gboolean internal_enumerator;
3122 gboolean eclass_is_valuetype;
3124 if (!mono_defaults.generic_ilist_class) {
3128 internal_enumerator = FALSE;
3129 eclass_is_valuetype = FALSE;
3130 original_rank = eclass->rank;
3131 if (klass->byval_arg.type != MONO_TYPE_SZARRAY) {
3132 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
3133 if (gklass && klass->nested_in == mono_defaults.array_class && strcmp (klass->name, "InternalEnumerator`1") == 0) {
3135 * For a Enumerator<T[]> we need to get the list of interfaces for T.
3137 eclass = mono_class_from_mono_type (gklass->context.class_inst->type_argv [0]);
3138 original_rank = eclass->rank;
3140 eclass = eclass->element_class;
3141 internal_enumerator = TRUE;
3142 *is_enumerator = TRUE;
3150 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
3151 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
3153 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
3155 generic_icollection_class = mono_class_get_generic_icollection_class ();
3156 generic_ienumerable_class = mono_class_get_generic_ienumerable_class ();
3157 generic_ienumerator_class = mono_class_get_generic_ienumerator_class ();
3158 generic_ireadonlylist_class = mono_class_get_generic_ireadonlylist_class ();
3159 generic_ireadonlycollection_class = mono_class_get_generic_ireadonlycollection_class ();
3161 mono_class_init (eclass);
3164 * Arrays in 2.0 need to implement a number of generic interfaces
3165 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
3166 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
3167 * We collect the types needed to build the
3168 * instantiations in interfaces at intervals of 3/5, because 3/5 are
3169 * the generic interfaces needed to implement.
3171 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
3172 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
3174 if (eclass->valuetype) {
3175 nifaces = generic_ireadonlylist_class ? 5 : 3;
3176 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
3178 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
3179 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
3180 if (internal_enumerator) {
3182 if (valuetype_types [1])
3186 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3187 interfaces [0] = valuetype_types [0];
3188 if (valuetype_types [1])
3189 interfaces [nifaces] = valuetype_types [1];
3191 eclass_is_valuetype = TRUE;
3194 int idepth = eclass->idepth;
3195 if (!internal_enumerator)
3197 nifaces = generic_ireadonlylist_class ? 2 : 3;
3199 // FIXME: This doesn't seem to work/required for generic params
3200 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
3201 mono_class_setup_interface_offsets (eclass);
3203 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
3204 /* we add object for interfaces and the supertypes for the other
3205 * types. The last of the supertypes is the element class itself which we
3206 * already created the explicit interfaces for (so we include it for IEnumerator
3207 * and exclude it for arrays).
3209 if (MONO_CLASS_IS_INTERFACE (eclass))
3212 interface_count += idepth;
3213 if (eclass->rank && eclass->element_class->valuetype) {
3214 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3215 if (valuetype_types [1])
3218 /* IList, ICollection, IEnumerable, IReadOnlyList */
3219 interface_count *= nifaces;
3220 real_count = interface_count;
3221 if (internal_enumerator) {
3222 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3223 if (valuetype_types [1])
3226 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3227 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3228 interfaces [0] = mono_defaults.object_class;
3232 for (i = 0; i < idepth; i++) {
3233 mono_class_init (eclass->supertypes [i]);
3234 interfaces [j] = eclass->supertypes [i];
3238 if (all_interfaces) {
3239 for (i = 0; i < eclass->interface_offsets_count; i++) {
3240 interfaces [j] = eclass->interfaces_packed [i];
3244 for (i = 0; i < eclass->interface_count; i++) {
3245 interfaces [j] = eclass->interfaces [i];
3249 if (valuetype_types [1]) {
3250 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3255 /* instantiate the generic interfaces */
3256 for (i = 0; i < interface_count; i += nifaces) {
3257 MonoClass *iface = interfaces [i];
3259 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3260 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3262 if (eclass->valuetype) {
3263 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3264 if (generic_ireadonlylist_class) {
3265 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3266 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3269 if (!generic_ireadonlylist_class)
3270 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3273 if (internal_enumerator) {
3275 /* instantiate IEnumerator<iface> */
3276 for (i = 0; i < interface_count; i++) {
3277 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3279 j = interface_count;
3280 if (!eclass_is_valuetype) {
3281 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3282 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3285 for (i = 0; i < eclass->idepth; i++) {
3286 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3290 for (i = 0; i < eclass->interface_offsets_count; i++) {
3291 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3295 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3297 if (valuetype_types [1])
3298 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3302 char *type_name = mono_type_get_name_full (&klass->byval_arg, 0);
3303 for (i = 0; i < real_count; ++i) {
3304 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3305 g_print ("%s implements %s\n", type_name, name);
3316 find_array_interface (MonoClass *klass, const char *name)
3319 for (i = 0; i < klass->interface_count; ++i) {
3320 if (strcmp (klass->interfaces [i]->name, name) == 0)
3327 * Return the number of virtual methods.
3328 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3329 * Return -1 on failure.
3330 * FIXME It would be nice if this information could be cached somewhere.
3333 count_virtual_methods (MonoClass *klass)
3335 int i, mcount, vcount = 0;
3337 klass = mono_class_get_generic_type_definition (klass); /*We can find this information by looking at the GTD*/
3339 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
3340 mono_class_setup_methods (klass);
3341 if (mono_class_has_failure (klass))
3344 mcount = mono_class_get_method_count (klass);
3345 for (i = 0; i < mcount; ++i) {
3346 flags = klass->methods [i]->flags;
3347 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3351 int first_idx = mono_class_get_first_method_idx (klass);
3352 mcount = mono_class_get_method_count (klass);
3353 for (i = 0; i < mcount; ++i) {
3354 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
3356 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3364 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3372 m = (l + num_ifaces) / 2;
3373 if (interfaces_full [m] == ic)
3375 if (l == num_ifaces)
3377 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3386 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3388 int i = find_interface (num_ifaces, interfaces_full, ic);
3390 return interface_offsets_full [i];
3395 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3397 int i = find_interface (num_ifaces, interfaces_full, ic);
3401 interface_offsets_full [i] = offset;
3404 for (i = 0; i < num_ifaces; ++i) {
3405 if (interfaces_full [i]) {
3407 if (interfaces_full [i]->interface_id < ic->interface_id)
3410 while (end < num_ifaces && interfaces_full [end]) end++;
3411 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3412 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3414 interfaces_full [i] = ic;
3415 interface_offsets_full [i] = offset;
3421 #ifdef COMPRESSED_INTERFACE_BITMAP
3424 * Compressed interface bitmap design.
3426 * Interface bitmaps take a large amount of memory, because their size is
3427 * linear with the maximum interface id assigned in the process (each interface
3428 * is assigned a unique id as it is loaded). The number of interface classes
3429 * is high because of the many implicit interfaces implemented by arrays (we'll
3430 * need to lazy-load them in the future).
3431 * Most classes implement a very small number of interfaces, so the bitmap is
3432 * sparse. This bitmap needs to be checked by interface casts, so access to the
3433 * needed bit must be fast and doable with few jit instructions.
3435 * The current compression format is as follows:
3436 * *) it is a sequence of one or more two-byte elements
3437 * *) the first byte in the element is the count of empty bitmap bytes
3438 * at the current bitmap position
3439 * *) the second byte in the element is an actual bitmap byte at the current
3442 * As an example, the following compressed bitmap bytes:
3443 * 0x07 0x01 0x00 0x7
3444 * correspond to the following bitmap:
3445 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3447 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3448 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3449 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3453 * mono_compress_bitmap:
3454 * @dest: destination buffer
3455 * @bitmap: bitmap buffer
3456 * @size: size of @bitmap in bytes
3458 * This is a mono internal function.
3459 * The @bitmap data is compressed into a format that is small but
3460 * still searchable in few instructions by the JIT and runtime.
3461 * The compressed data is stored in the buffer pointed to by the
3462 * @dest array. Passing a #NULL value for @dest allows to just compute
3463 * the size of the buffer.
3464 * This compression algorithm assumes the bits set in the bitmap are
3465 * few and far between, like in interface bitmaps.
3466 * Returns: The size of the compressed bitmap in bytes.
3469 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3473 const uint8_t *end = bitmap + size;
3474 while (bitmap < end) {
3475 if (*bitmap || numz == 255) {
3499 * mono_class_interface_match:
3500 * @bitmap: a compressed bitmap buffer
3501 * @id: the index to check in the bitmap
3503 * This is a mono internal function.
3504 * Checks if a bit is set in a compressed interface bitmap. @id must
3505 * be already checked for being smaller than the maximum id encoded in the
3508 * Returns: A non-zero value if bit @id is set in the bitmap @bitmap,
3512 mono_class_interface_match (const uint8_t *bitmap, int id)
3515 id -= bitmap [0] * 8;
3519 return bitmap [1] & (1 << id);
3528 * Return -1 on failure and set klass->has_failure and store a MonoErrorBoxed with the details.
3529 * LOCKING: Acquires the loader lock.
3532 setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite)
3536 int i, j, num_ifaces;
3538 MonoClass **interfaces_full = NULL;
3539 int *interface_offsets_full = NULL;
3541 GPtrArray **ifaces_array = NULL;
3542 int interface_offsets_count;
3543 MonoClass **array_interfaces = NULL;
3544 int num_array_interfaces;
3545 int is_enumerator = FALSE;
3547 mono_loader_lock ();
3549 mono_class_setup_supertypes (klass);
3551 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3552 * implicit interfaces have the property that they are assigned the same slot in the
3553 * vtables for compatible interfaces
3555 array_interfaces = get_implicit_generic_array_interfaces (klass, &num_array_interfaces, &is_enumerator);
3557 /* compute maximum number of slots and maximum interface id */
3559 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3560 ifaces_array = g_new0 (GPtrArray *, klass->idepth);
3561 for (j = 0; j < klass->idepth; j++) {
3562 k = klass->supertypes [j];
3564 num_ifaces += k->interface_count;
3565 for (i = 0; i < k->interface_count; i++) {
3566 ic = k->interfaces [i];
3568 mono_class_init (ic);
3570 if (max_iid < ic->interface_id)
3571 max_iid = ic->interface_id;
3573 ifaces = mono_class_get_implemented_interfaces (k, &error);
3574 if (!mono_error_ok (&error)) {
3575 char *name = mono_type_get_full_name (k);
3576 mono_class_set_type_load_failure (klass, "Error getting the interfaces of %s due to %s", name, mono_error_get_message (&error));
3578 mono_error_cleanup (&error);
3583 num_ifaces += ifaces->len;
3584 for (i = 0; i < ifaces->len; ++i) {
3585 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3586 if (max_iid < ic->interface_id)
3587 max_iid = ic->interface_id;
3589 ifaces_array [j] = ifaces;
3593 for (i = 0; i < num_array_interfaces; ++i) {
3594 ic = array_interfaces [i];
3595 mono_class_init (ic);
3596 if (max_iid < ic->interface_id)
3597 max_iid = ic->interface_id;
3600 if (MONO_CLASS_IS_INTERFACE (klass)) {
3602 if (max_iid < klass->interface_id)
3603 max_iid = klass->interface_id;
3606 /* compute vtable offset for interfaces */
3607 interfaces_full = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3608 interface_offsets_full = (int *)g_malloc (sizeof (int) * num_ifaces);
3610 for (i = 0; i < num_ifaces; i++)
3611 interface_offsets_full [i] = -1;
3613 /* skip the current class */
3614 for (j = 0; j < klass->idepth - 1; j++) {
3615 k = klass->supertypes [j];
3616 ifaces = ifaces_array [j];
3619 for (i = 0; i < ifaces->len; ++i) {
3621 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3623 /*Force the sharing of interface offsets between parent and subtypes.*/
3624 io = mono_class_interface_offset (k, ic);
3626 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3631 g_assert (klass == klass->supertypes [klass->idepth - 1]);
3632 ifaces = ifaces_array [klass->idepth - 1];
3634 for (i = 0; i < ifaces->len; ++i) {
3636 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3637 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3639 count = count_virtual_methods (ic);
3641 char *name = mono_type_get_full_name (ic);
3642 mono_class_set_type_load_failure (klass, "Error calculating interface offset of %s", name);
3651 if (MONO_CLASS_IS_INTERFACE (klass))
3652 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, klass, cur_slot, TRUE);
3654 if (num_array_interfaces) {
3655 if (is_enumerator) {
3656 int ienumerator_idx = find_array_interface (klass, "IEnumerator`1");
3657 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ienumerator_idx]);
3658 g_assert (ienumerator_offset >= 0);
3659 for (i = 0; i < num_array_interfaces; ++i) {
3660 ic = array_interfaces [i];
3661 if (strcmp (ic->name, "IEnumerator`1") == 0)
3662 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3664 g_assert_not_reached ();
3665 /*g_print ("type %s has %s offset at %d (%s)\n", klass->name, ic->name, interface_offsets_full [ic->interface_id], klass->interfaces [0]->name);*/
3668 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3669 int ilist_iface_idx = find_array_interface (klass, "IList`1");
3670 MonoClass* ilist_class = klass->interfaces [ilist_iface_idx];
3671 int ireadonlylist_iface_idx = find_array_interface (klass, "IReadOnlyList`1");
3672 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? klass->interfaces [ireadonlylist_iface_idx] : NULL;
3673 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3674 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3675 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3676 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ilist_iface_idx]);
3677 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3678 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3679 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ireadonlylist_iface_idx]) : -1;
3680 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3681 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3682 for (i = 0; i < num_array_interfaces; ++i) {
3684 ic = array_interfaces [i];
3685 if (mono_class_get_generic_class (ic)->container_class == mono_defaults.generic_ilist_class)
3686 offset = ilist_offset;
3687 else if (strcmp (ic->name, "ICollection`1") == 0)
3688 offset = icollection_offset;
3689 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3690 offset = ienumerable_offset;
3691 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3692 offset = ireadonlylist_offset;
3693 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3694 offset = ireadonlycollection_offset;
3696 g_assert_not_reached ();
3697 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3698 /*g_print ("type %s has %s offset at %d (%s)\n", klass->name, ic->name, offset, klass->interfaces [0]->name);*/
3703 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3704 if (interface_offsets_full [i] != -1)
3705 interface_offsets_count ++;
3708 /* Publish the data */
3709 klass->max_interface_id = max_iid;
3711 * We might get called multiple times:
3712 * - mono_class_init ()
3713 * - mono_class_setup_vtable ().
3714 * - mono_class_setup_interface_offsets ().
3715 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3716 * means we have to overwrite those when called from other places (#4440).
3718 if (klass->interfaces_packed) {
3720 g_assert (klass->interface_offsets_count == interface_offsets_count);
3724 klass->interface_offsets_count = interface_offsets_count;
3725 klass->interfaces_packed = (MonoClass **)mono_class_alloc (klass, sizeof (MonoClass*) * interface_offsets_count);
3726 klass->interface_offsets_packed = (guint16 *)mono_class_alloc (klass, sizeof (guint16) * interface_offsets_count);
3727 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3728 #ifdef COMPRESSED_INTERFACE_BITMAP
3729 bitmap = g_malloc0 (bsize);
3731 bitmap = (uint8_t *)mono_class_alloc0 (klass, bsize);
3733 for (i = 0; i < interface_offsets_count; i++) {
3734 guint32 id = interfaces_full [i]->interface_id;
3735 bitmap [id >> 3] |= (1 << (id & 7));
3736 klass->interfaces_packed [i] = interfaces_full [i];
3737 klass->interface_offsets_packed [i] = interface_offsets_full [i];
3738 /*if (num_array_interfaces)
3739 g_print ("type %s has %s offset at %d\n", mono_type_get_name_full (&klass->byval_arg, 0), mono_type_get_name_full (&interfaces_full [i]->byval_arg, 0), interface_offsets_full [i]);*/
3741 #ifdef COMPRESSED_INTERFACE_BITMAP
3742 i = mono_compress_bitmap (NULL, bitmap, bsize);
3743 klass->interface_bitmap = mono_class_alloc0 (klass, i);
3744 mono_compress_bitmap (klass->interface_bitmap, bitmap, bsize);
3747 klass->interface_bitmap = bitmap;
3751 mono_loader_unlock ();
3753 g_free (interfaces_full);
3754 g_free (interface_offsets_full);
3755 g_free (array_interfaces);
3756 for (i = 0; i < klass->idepth; i++) {
3757 ifaces = ifaces_array [i];
3759 g_ptr_array_free (ifaces, TRUE);
3761 g_free (ifaces_array);
3763 //printf ("JUST DONE: ");
3764 //print_implemented_interfaces (klass);
3770 * Setup interface offsets for interfaces.
3772 * - klass->max_interface_id
3773 * - klass->interface_offsets_count
3774 * - klass->interfaces_packed
3775 * - klass->interface_offsets_packed
3776 * - klass->interface_bitmap
3778 * This function can fail @class.
3781 mono_class_setup_interface_offsets (MonoClass *klass)
3783 setup_interface_offsets (klass, 0, FALSE);
3786 /*Checks if @klass has @parent as one of it's parents type gtd
3790 * Bar<T> : Foo<Bar<Bar<T>>>
3794 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3796 klass = mono_class_get_generic_type_definition (klass);
3797 parent = mono_class_get_generic_type_definition (parent);
3798 mono_class_setup_supertypes (klass);
3799 mono_class_setup_supertypes (parent);
3801 return klass->idepth >= parent->idepth &&
3802 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3806 mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup)
3808 MonoGenericInst *ginst;
3811 if (!mono_class_is_ginst (klass)) {
3812 mono_class_setup_vtable_full (klass, in_setup);
3813 return !mono_class_has_failure (klass);
3816 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup);
3817 if (mono_class_set_type_load_failure_causedby_class (klass, mono_class_get_generic_class (klass)->container_class, "Failed to load generic definition vtable"))
3820 ginst = mono_class_get_generic_class (klass)->context.class_inst;
3821 for (i = 0; i < ginst->type_argc; ++i) {
3823 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3825 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3826 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3827 if (mono_class_has_gtd_parent (klass, arg) || mono_class_has_gtd_parent (arg, klass))
3829 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3830 mono_class_set_type_load_failure (klass, "Failed to load generic parameter %d", i);
3838 * mono_class_setup_vtable:
3840 * Creates the generic vtable of CLASS.
3841 * Initializes the following fields in MonoClass:
3844 * Plus all the fields initialized by setup_interface_offsets ().
3845 * If there is an error during vtable construction, klass->has_failure
3846 * is set and details are stored in a MonoErrorBoxed.
3848 * LOCKING: Acquires the loader lock.
3851 mono_class_setup_vtable (MonoClass *klass)
3853 mono_class_setup_vtable_full (klass, NULL);
3857 mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
3860 MonoMethod **overrides;
3861 MonoGenericContext *context;
3869 if (MONO_CLASS_IS_INTERFACE (klass)) {
3870 /* This sets method->slot for all methods if this is an interface */
3871 mono_class_setup_methods (klass);
3875 if (mono_class_has_failure (klass))
3878 if (g_list_find (in_setup, klass))
3881 mono_loader_lock ();
3883 if (klass->vtable) {
3884 mono_loader_unlock ();
3888 mono_stats.generic_vtable_count ++;
3889 in_setup = g_list_prepend (in_setup, klass);
3891 if (mono_class_is_ginst (klass)) {
3892 if (!mono_class_check_vtable_constraints (klass, in_setup)) {
3893 mono_loader_unlock ();
3894 g_list_remove (in_setup, klass);
3898 context = mono_class_get_context (klass);
3899 type_token = mono_class_get_generic_class (klass)->container_class->type_token;
3901 context = (MonoGenericContext *) mono_class_try_get_generic_container (klass); //FIXME is this a case of a try?
3902 type_token = klass->type_token;
3905 if (image_is_dynamic (klass->image)) {
3906 /* Generic instances can have zero method overrides without causing any harm.
3907 * This is true since we don't do layout all over again for them, we simply inflate
3908 * the layout of the parent.
3910 mono_reflection_get_dynamic_overrides (klass, &overrides, &onum, &error);
3911 if (!is_ok (&error)) {
3912 mono_loader_unlock ();
3913 g_list_remove (in_setup, klass);
3914 mono_class_set_type_load_failure (klass, "Could not load list of method overrides due to %s", mono_error_get_message (&error));
3915 mono_error_cleanup (&error);
3919 /* The following call fails if there are missing methods in the type */
3920 /* FIXME it's probably a good idea to avoid this for generic instances. */
3921 ok = mono_class_get_overrides_full (klass->image, type_token, &overrides, &onum, context);
3925 mono_class_setup_vtable_general (klass, overrides, onum, in_setup);
3927 mono_class_set_type_load_failure (klass, "Could not load list of method overrides");
3931 mono_loader_unlock ();
3932 g_list_remove (in_setup, klass);
3937 #define DEBUG_INTERFACE_VTABLE_CODE 0
3938 #define TRACE_INTERFACE_VTABLE_CODE 0
3939 #define VERIFY_INTERFACE_VTABLE_CODE 0
3940 #define VTABLE_SELECTOR (1)
3942 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3943 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3944 if (!(VTABLE_SELECTOR)) break; \
3948 #define DEBUG_INTERFACE_VTABLE(stmt)
3951 #if TRACE_INTERFACE_VTABLE_CODE
3952 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3953 if (!(VTABLE_SELECTOR)) break; \
3957 #define TRACE_INTERFACE_VTABLE(stmt)
3960 #if VERIFY_INTERFACE_VTABLE_CODE
3961 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3962 if (!(VTABLE_SELECTOR)) break; \
3966 #define VERIFY_INTERFACE_VTABLE(stmt)
3970 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3972 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3976 GString *res = g_string_new ("");
3978 g_string_append_c (res, '(');
3979 for (i = 0; i < sig->param_count; ++i) {
3981 g_string_append_c (res, ',');
3982 mono_type_get_desc (res, sig->params [i], include_namespace);
3984 g_string_append (res, ")=>");
3985 if (sig->ret != NULL) {
3986 mono_type_get_desc (res, sig->ret, include_namespace);
3988 g_string_append (res, "NULL");
3991 g_string_free (res, FALSE);
3995 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3996 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3997 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3998 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
4006 is_wcf_hack_disabled (void)
4008 static gboolean disabled;
4009 static gboolean inited = FALSE;
4011 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
4018 check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
4020 MonoMethodSignature *cmsig, *imsig;
4021 if (strcmp (im->name, cm->name) == 0) {
4022 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
4023 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
4026 if (! slot_is_empty) {
4027 if (require_newslot) {
4028 if (! interface_is_explicitly_implemented_by_class) {
4029 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
4032 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4033 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
4037 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
4040 cmsig = mono_method_signature (cm);
4041 imsig = mono_method_signature (im);
4042 if (!cmsig || !imsig) {
4043 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
4047 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4048 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
4049 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4050 TRACE_INTERFACE_VTABLE (printf ("]"));
4053 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
4054 if (mono_security_core_clr_enabled ())
4055 mono_security_core_clr_check_override (klass, cm, im);
4057 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
4058 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4059 char *body_name = mono_method_full_name (cm, TRUE);
4060 char *decl_name = mono_method_full_name (im, TRUE);
4061 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4069 MonoClass *ic = im->klass;
4070 const char *ic_name_space = ic->name_space;
4071 const char *ic_name = ic->name;
4074 if (! require_newslot) {
4075 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
4078 if (cm->klass->rank == 0) {
4079 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
4082 cmsig = mono_method_signature (cm);
4083 imsig = mono_method_signature (im);
4084 if (!cmsig || !imsig) {
4085 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
4089 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4090 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
4091 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4092 TRACE_INTERFACE_VTABLE (printf ("]"));
4095 if (mono_class_get_image (ic) != mono_defaults.corlib) {
4096 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
4099 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
4100 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
4103 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))) {
4104 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
4108 subname = strstr (cm->name, ic_name_space);
4109 if (subname != cm->name) {
4110 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
4113 subname += strlen (ic_name_space);
4114 if (subname [0] != '.') {
4115 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
4119 if (strstr (subname, ic_name) != subname) {
4120 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
4123 subname += strlen (ic_name);
4124 if (subname [0] != '.') {
4125 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
4129 if (strcmp (subname, im->name) != 0) {
4130 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
4134 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
4135 if (mono_security_core_clr_enabled ())
4136 mono_security_core_clr_check_override (klass, cm, im);
4138 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
4139 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4140 char *body_name = mono_method_full_name (cm, TRUE);
4141 char *decl_name = mono_method_full_name (im, TRUE);
4142 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4152 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
4154 foreach_override (gpointer key, gpointer value, gpointer user_data) {
4155 MonoMethod *method = key;
4156 MonoMethod *override = value;
4157 MonoClass *method_class = mono_method_get_class (method);
4158 MonoClass *override_class = mono_method_get_class (override);
4160 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
4161 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
4162 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
4165 print_overrides (GHashTable *override_map, const char *message) {
4167 printf ("Override map \"%s\" START:\n", message);
4168 g_hash_table_foreach (override_map, foreach_override, NULL);
4169 printf ("Override map \"%s\" END.\n", message);
4171 printf ("Override map \"%s\" EMPTY.\n", message);
4175 print_vtable_full (MonoClass *klass, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
4176 char *full_name = mono_type_full_name (&klass->byval_arg);
4180 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
4182 if (print_interfaces) {
4183 print_implemented_interfaces (klass);
4184 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
4187 if (klass->parent) {
4188 parent_size = klass->parent->vtable_size;
4192 for (i = 0; i < size; ++i) {
4193 MonoMethod *cm = vtable [i];
4194 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
4195 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
4197 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
4205 #if VERIFY_INTERFACE_VTABLE_CODE
4207 mono_method_try_get_vtable_index (MonoMethod *method)
4209 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4210 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4211 if (imethod->declaring->is_generic)
4212 return imethod->declaring->slot;
4214 return method->slot;
4218 mono_class_verify_vtable (MonoClass *klass)
4221 char *full_name = mono_type_full_name (&klass->byval_arg);
4223 printf ("*** Verifying VTable of class '%s' \n", full_name);
4227 if (!klass->methods)
4230 count = mono_class_method_count (klass);
4231 for (i = 0; i < count; ++i) {
4232 MonoMethod *cm = klass->methods [i];
4235 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4239 full_name = mono_method_full_name (cm, TRUE);
4241 slot = mono_method_try_get_vtable_index (cm);
4243 if (slot >= klass->vtable_size) {
4244 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, klass->vtable_size);
4248 if (slot >= 0 && klass->vtable [slot] != cm && (klass->vtable [slot])) {
4249 char *other_name = klass->vtable [slot] ? mono_method_full_name (klass->vtable [slot], TRUE) : g_strdup ("[null value]");
4250 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4251 g_free (other_name);
4254 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4261 print_unimplemented_interface_method_info (MonoClass *klass, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum)
4264 char *method_signature;
4267 for (index = 0; index < onum; ++index) {
4268 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4269 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4271 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4272 type_name = mono_type_full_name (&klass->byval_arg);
4273 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4274 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4275 g_free (method_signature);
4277 mono_class_setup_methods (klass);
4278 if (mono_class_has_failure (klass)) {
4279 char *name = mono_type_get_full_name (klass);
4280 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4284 mcount = mono_class_get_method_count (klass);
4285 for (index = 0; index < mcount; ++index) {
4286 MonoMethod *cm = klass->methods [index];
4287 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4289 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4290 g_free (method_signature);
4295 mono_method_get_method_definition (MonoMethod *method)
4297 while (method->is_inflated)
4298 method = ((MonoMethodInflated*)method)->declaring;
4303 verify_class_overrides (MonoClass *klass, MonoMethod **overrides, int onum)
4307 for (i = 0; i < onum; ++i) {
4308 MonoMethod *decl = overrides [i * 2];
4309 MonoMethod *body = overrides [i * 2 + 1];
4311 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (klass)) {
4312 mono_class_set_type_load_failure (klass, "Method belongs to a different class than the declared one");
4316 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4317 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4318 mono_class_set_type_load_failure (klass, "Method must not be static to override a base type");
4320 mono_class_set_type_load_failure (klass, "Method must be virtual to override a base type");
4324 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4325 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4326 mono_class_set_type_load_failure (klass, "Cannot override a static method in a base type");
4328 mono_class_set_type_load_failure (klass, "Cannot override a non virtual method in a base type");
4332 if (!mono_class_is_assignable_from_slow (decl->klass, klass)) {
4333 mono_class_set_type_load_failure (klass, "Method overrides a class or interface that is not extended or implemented by this type");
4337 body = mono_method_get_method_definition (body);
4338 decl = mono_method_get_method_definition (decl);
4340 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4341 char *body_name = mono_method_full_name (body, TRUE);
4342 char *decl_name = mono_method_full_name (decl, TRUE);
4343 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4353 mono_class_need_stelemref_method (MonoClass *klass)
4355 return klass->rank == 1 && MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg);
4359 * LOCKING: this is supposed to be called with the loader lock held.
4362 mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int onum, GList *in_setup)
4366 MonoMethod **vtable;
4367 int i, max_vtsize = 0, cur_slot = 0;
4369 GPtrArray *ifaces = NULL;
4370 GHashTable *override_map = NULL;
4372 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4373 int first_non_interface_slot;
4375 GSList *virt_methods = NULL, *l;
4376 int stelemref_slot = 0;
4381 if (overrides && !verify_class_overrides (klass, overrides, onum))
4384 ifaces = mono_class_get_implemented_interfaces (klass, &error);
4385 if (!mono_error_ok (&error)) {
4386 char *name = mono_type_get_full_name (klass);
4387 mono_class_set_type_load_failure (klass, "Could not resolve %s interfaces due to %s", name, mono_error_get_message (&error));
4389 mono_error_cleanup (&error);
4391 } else if (ifaces) {
4392 for (i = 0; i < ifaces->len; i++) {
4393 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
4394 max_vtsize += mono_class_get_method_count (ic);
4396 g_ptr_array_free (ifaces, TRUE);
4400 if (klass->parent) {
4401 mono_class_init (klass->parent);
4402 mono_class_setup_vtable_full (klass->parent, in_setup);
4404 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class failed to load"))
4407 max_vtsize += klass->parent->vtable_size;
4408 cur_slot = klass->parent->vtable_size;
4411 max_vtsize += mono_class_get_method_count (klass);
4413 /*Array have a slot for stelemref*/
4414 if (mono_class_need_stelemref_method (klass)) {
4415 stelemref_slot = cur_slot;
4420 vtable = (MonoMethod **)alloca (sizeof (gpointer) * max_vtsize);
4421 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4423 /* printf ("METAINIT %s.%s\n", klass->name_space, klass->name); */
4425 cur_slot = setup_interface_offsets (klass, cur_slot, TRUE);
4426 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4429 max_iid = klass->max_interface_id;
4430 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4432 /* Optimized version for generic instances */
4433 if (mono_class_is_ginst (klass)) {
4435 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4438 mono_class_setup_vtable_full (gklass, in_setup);
4439 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Could not load generic definition"))
4442 tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * gklass->vtable_size);
4443 klass->vtable_size = gklass->vtable_size;
4444 for (i = 0; i < gklass->vtable_size; ++i)
4445 if (gklass->vtable [i]) {
4446 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], klass, mono_class_get_context (klass), &error);
4447 if (!mono_error_ok (&error)) {
4448 mono_class_set_type_load_failure (klass, "Could not inflate method due to %s", mono_error_get_message (&error));
4449 mono_error_cleanup (&error);
4453 tmp [i]->slot = gklass->vtable [i]->slot;
4455 mono_memory_barrier ();
4456 klass->vtable = tmp;
4458 /* Have to set method->slot for abstract virtual methods */
4459 if (klass->methods && gklass->methods) {
4460 int mcount = mono_class_get_method_count (klass);
4461 for (i = 0; i < mcount; ++i)
4462 if (klass->methods [i]->slot == -1)
4463 klass->methods [i]->slot = gklass->methods [i]->slot;
4469 if (klass->parent && klass->parent->vtable_size) {
4470 MonoClass *parent = klass->parent;
4473 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4475 // Also inherit parent interface vtables, just as a starting point.
4476 // This is needed otherwise bug-77127.exe fails when the property methods
4477 // have different names in the iterface and the class, because for child
4478 // classes the ".override" information is not used anymore.
4479 for (i = 0; i < parent->interface_offsets_count; i++) {
4480 MonoClass *parent_interface = parent->interfaces_packed [i];
4481 int interface_offset = mono_class_interface_offset (klass, parent_interface);
4482 /*FIXME this is now dead code as this condition will never hold true.
4483 Since interface offsets are inherited then the offset of an interface implemented
4484 by a parent will never be the out of it's vtable boundary.
4486 if (interface_offset >= parent->vtable_size) {
4487 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4490 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4491 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4492 int mcount = mono_class_get_method_count (parent_interface);
4493 for (j = 0; j < mcount && !mono_class_has_failure (klass); j++) {
4494 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4495 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4496 parent_interface_offset + j, parent_interface_offset, j,
4497 interface_offset + j, interface_offset, j));
4504 /*Array have a slot for stelemref*/
4505 if (mono_class_need_stelemref_method (klass)) {
4506 MonoMethod *method = mono_marshal_get_virtual_stelemref (klass);
4508 method->slot = stelemref_slot;
4510 g_assert (method->slot == stelemref_slot);
4512 vtable [stelemref_slot] = method;
4515 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4516 /* override interface methods */
4517 for (i = 0; i < onum; i++) {
4518 MonoMethod *decl = overrides [i*2];
4519 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4521 dslot = mono_method_get_vtable_slot (decl);
4523 mono_class_set_type_load_failure (klass, "");
4527 dslot += mono_class_interface_offset (klass, decl->klass);
4528 vtable [dslot] = overrides [i*2 + 1];
4529 vtable [dslot]->slot = dslot;
4531 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4533 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4535 if (mono_security_core_clr_enabled ())
4536 mono_security_core_clr_check_override (klass, vtable [dslot], decl);
4539 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4540 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4543 * Create a list of virtual methods to avoid calling
4544 * mono_class_get_virtual_methods () which is slow because of the metadata
4548 gpointer iter = NULL;
4551 virt_methods = NULL;
4552 while ((cm = mono_class_get_virtual_methods (klass, &iter))) {
4553 virt_methods = g_slist_prepend (virt_methods, cm);
4555 if (mono_class_has_failure (klass))
4559 // Loop on all implemented interfaces...
4560 for (i = 0; i < klass->interface_offsets_count; i++) {
4561 MonoClass *parent = klass->parent;
4563 gboolean interface_is_explicitly_implemented_by_class;
4566 ic = klass->interfaces_packed [i];
4567 ic_offset = mono_class_interface_offset (klass, ic);
4569 mono_class_setup_methods (ic);
4570 if (mono_class_has_failure (ic))
4573 // Check if this interface is explicitly implemented (instead of just inherited)
4574 if (parent != NULL) {
4575 int implemented_interfaces_index;
4576 interface_is_explicitly_implemented_by_class = FALSE;
4577 for (implemented_interfaces_index = 0; implemented_interfaces_index < klass->interface_count; implemented_interfaces_index++) {
4578 if (ic == klass->interfaces [implemented_interfaces_index]) {
4579 interface_is_explicitly_implemented_by_class = TRUE;
4584 interface_is_explicitly_implemented_by_class = TRUE;
4587 // Loop on all interface methods...
4588 int mcount = mono_class_get_method_count (ic);
4589 for (im_index = 0; im_index < mcount; im_index++) {
4590 MonoMethod *im = ic->methods [im_index];
4591 int im_slot = ic_offset + im->slot;
4592 MonoMethod *override_im = (override_map != NULL) ? (MonoMethod *)g_hash_table_lookup (override_map, im) : NULL;
4594 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4597 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4599 // If there is an explicit implementation, just use it right away,
4600 // otherwise look for a matching method
4601 if (override_im == NULL) {
4605 // First look for a suitable method among the class methods
4606 for (l = virt_methods; l; l = l->next) {
4607 cm = (MonoMethod *)l->data;
4608 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)));
4609 if (check_interface_method_override (klass, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
4610 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4611 vtable [im_slot] = cm;
4612 /* Why do we need this? */
4617 TRACE_INTERFACE_VTABLE (printf ("\n"));
4618 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4622 // If the slot is still empty, look in all the inherited virtual methods...
4623 if ((vtable [im_slot] == NULL) && klass->parent != NULL) {
4624 MonoClass *parent = klass->parent;
4625 // Reverse order, so that last added methods are preferred
4626 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4627 MonoMethod *cm = parent->vtable [cm_index];
4629 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));
4630 if ((cm != NULL) && check_interface_method_override (klass, im, cm, FALSE, FALSE, TRUE)) {
4631 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4632 vtable [im_slot] = cm;
4633 /* Why do we need this? */
4639 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4641 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4645 g_assert (vtable [im_slot] == override_im);
4650 // If the class is not abstract, check that all its interface slots are full.
4651 // The check is done here and not directly at the end of the loop above because
4652 // it can happen (for injected generic array interfaces) that the same slot is
4653 // processed multiple times (those interfaces have overlapping slots), and it
4654 // will not always be the first pass the one that fills the slot.
4655 if (!mono_class_is_abstract (klass)) {
4656 for (i = 0; i < klass->interface_offsets_count; i++) {
4660 ic = klass->interfaces_packed [i];
4661 ic_offset = mono_class_interface_offset (klass, ic);
4663 int mcount = mono_class_get_method_count (ic);
4664 for (im_index = 0; im_index < mcount; im_index++) {
4665 MonoMethod *im = ic->methods [im_index];
4666 int im_slot = ic_offset + im->slot;
4668 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4671 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4672 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4673 if (vtable [im_slot] == NULL) {
4674 print_unimplemented_interface_method_info (klass, ic, im, im_slot, overrides, onum);
4681 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4682 for (l = virt_methods; l; l = l->next) {
4683 cm = (MonoMethod *)l->data;
4685 * If the method is REUSE_SLOT, we must check in the
4686 * base class for a method to override.
4688 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4690 for (k = klass->parent; k ; k = k->parent) {
4695 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4696 MonoMethodSignature *cmsig, *m1sig;
4698 cmsig = mono_method_signature (cm);
4699 m1sig = mono_method_signature (m1);
4701 if (!cmsig || !m1sig) {
4702 /* FIXME proper error message */
4703 mono_class_set_type_load_failure (klass, "");
4707 if (!strcmp(cm->name, m1->name) &&
4708 mono_metadata_signature_equal (cmsig, m1sig)) {
4710 if (mono_security_core_clr_enabled ())
4711 mono_security_core_clr_check_override (klass, cm, m1);
4713 slot = mono_method_get_vtable_slot (m1);
4717 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4718 char *body_name = mono_method_full_name (cm, TRUE);
4719 char *decl_name = mono_method_full_name (m1, TRUE);
4720 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4726 g_assert (cm->slot < max_vtsize);
4728 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4729 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4730 mono_method_full_name (m1, 1), m1,
4731 mono_method_full_name (cm, 1), cm));
4732 g_hash_table_insert (override_map, m1, cm);
4736 if (mono_class_has_failure (k))
4746 /*Non final newslot methods must be given a non-interface vtable slot*/
4747 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4751 cm->slot = cur_slot++;
4753 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4754 vtable [cm->slot] = cm;
4757 /* override non interface methods */
4758 for (i = 0; i < onum; i++) {
4759 MonoMethod *decl = overrides [i*2];
4760 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4761 g_assert (decl->slot != -1);
4762 vtable [decl->slot] = overrides [i*2 + 1];
4763 overrides [i * 2 + 1]->slot = decl->slot;
4765 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4766 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4767 mono_method_full_name (decl, 1), decl,
4768 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4769 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4771 if (mono_security_core_clr_enabled ())
4772 mono_security_core_clr_check_override (klass, vtable [decl->slot], decl);
4777 * If a method occupies more than one place in the vtable, and it is
4778 * overriden, then change the other occurances too.
4783 for (i = 0; i < max_vtsize; ++i)
4785 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4787 cm = (MonoMethod *)g_hash_table_lookup (override_map, vtable [i]);
4792 g_hash_table_destroy (override_map);
4793 override_map = NULL;
4796 g_slist_free (virt_methods);
4797 virt_methods = NULL;
4799 /* Ensure that all vtable slots are filled with concrete instance methods */
4800 if (!mono_class_is_abstract (klass)) {
4801 for (i = 0; i < cur_slot; ++i) {
4802 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4803 char *type_name = mono_type_get_full_name (klass);
4804 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4805 mono_class_set_type_load_failure (klass, "Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name);
4807 g_free (method_name);
4813 if (mono_class_is_ginst (klass)) {
4814 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4816 mono_class_init (gklass);
4818 klass->vtable_size = MAX (gklass->vtable_size, cur_slot);
4820 /* Check that the vtable_size value computed in mono_class_init () is correct */
4821 if (klass->vtable_size)
4822 g_assert (cur_slot == klass->vtable_size);
4823 klass->vtable_size = cur_slot;
4826 /* Try to share the vtable with our parent. */
4827 if (klass->parent && (klass->parent->vtable_size == klass->vtable_size) && (memcmp (klass->parent->vtable, vtable, sizeof (gpointer) * klass->vtable_size) == 0)) {
4828 mono_memory_barrier ();
4829 klass->vtable = klass->parent->vtable;
4831 MonoMethod **tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * klass->vtable_size);
4832 memcpy (tmp, vtable, sizeof (gpointer) * klass->vtable_size);
4833 mono_memory_barrier ();
4834 klass->vtable = tmp;
4837 DEBUG_INTERFACE_VTABLE (print_vtable_full (klass, klass->vtable, klass->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4838 if (mono_print_vtable) {
4841 print_implemented_interfaces (klass);
4843 for (i = 0; i <= max_iid; i++)
4844 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
4847 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&klass->byval_arg),
4848 klass->vtable_size, icount);
4850 for (i = 0; i < cur_slot; ++i) {
4855 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4856 mono_method_full_name (cm, TRUE));
4862 printf ("Interfaces %s.%s (max_iid = %d)\n", klass->name_space,
4863 klass->name, max_iid);
4865 for (i = 0; i < klass->interface_count; i++) {
4866 ic = klass->interfaces [i];
4867 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4868 mono_class_interface_offset (klass, ic),
4869 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4872 for (k = klass->parent; k ; k = k->parent) {
4873 for (i = 0; i < k->interface_count; i++) {
4874 ic = k->interfaces [i];
4875 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4876 mono_class_interface_offset (klass, ic),
4877 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4883 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (klass));
4888 char *name = mono_type_get_full_name (klass);
4889 mono_class_set_type_load_failure (klass, "VTable setup of type %s failed", name);
4892 g_hash_table_destroy (override_map);
4894 g_slist_free (virt_methods);
4899 * mono_method_get_vtable_slot:
4901 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4902 * LOCKING: Acquires the loader lock.
4904 * FIXME Use proper MonoError machinery here.
4907 mono_method_get_vtable_slot (MonoMethod *method)
4909 if (method->slot == -1) {
4910 mono_class_setup_vtable (method->klass);
4911 if (mono_class_has_failure (method->klass))
4913 if (method->slot == -1) {
4917 if (!mono_class_is_ginst (method->klass)) {
4918 g_assert (method->is_inflated);
4919 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4922 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4923 g_assert (mono_class_is_ginst (method->klass));
4924 gklass = mono_class_get_generic_class (method->klass)->container_class;
4925 mono_class_setup_methods (method->klass);
4926 g_assert (method->klass->methods);
4927 mcount = mono_class_get_method_count (method->klass);
4928 for (i = 0; i < mcount; ++i) {
4929 if (method->klass->methods [i] == method)
4932 g_assert (i < mcount);
4933 g_assert (gklass->methods);
4934 method->slot = gklass->methods [i]->slot;
4936 g_assert (method->slot != -1);
4938 return method->slot;
4942 * mono_method_get_vtable_index:
4945 * Returns the index into the runtime vtable to access the method or,
4946 * in the case of a virtual generic method, the virtual generic method
4947 * thunk. Returns -1 on failure.
4949 * FIXME Use proper MonoError machinery here.
4952 mono_method_get_vtable_index (MonoMethod *method)
4954 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4955 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4956 if (imethod->declaring->is_generic)
4957 return mono_method_get_vtable_slot (imethod->declaring);
4959 return mono_method_get_vtable_slot (method);
4962 static MonoMethod *default_ghc = NULL;
4963 static MonoMethod *default_finalize = NULL;
4964 static int finalize_slot = -1;
4965 static int ghc_slot = -1;
4968 initialize_object_slots (MonoClass *klass)
4973 if (klass == mono_defaults.object_class) {
4974 mono_class_setup_vtable (klass);
4975 for (i = 0; i < klass->vtable_size; ++i) {
4976 MonoMethod *cm = klass->vtable [i];
4978 if (!strcmp (cm->name, "GetHashCode"))
4980 else if (!strcmp (cm->name, "Finalize"))
4984 g_assert (ghc_slot > 0);
4985 default_ghc = klass->vtable [ghc_slot];
4987 g_assert (finalize_slot > 0);
4988 default_finalize = klass->vtable [finalize_slot];
4993 MonoMethod *array_method;
4995 } GenericArrayMethodInfo;
4997 static int generic_array_method_num = 0;
4998 static GenericArrayMethodInfo *generic_array_method_info = NULL;
5001 generic_array_methods (MonoClass *klass)
5003 int i, count_generic = 0, mcount;
5004 GList *list = NULL, *tmp;
5005 if (generic_array_method_num)
5006 return generic_array_method_num;
5007 mono_class_setup_methods (klass->parent); /*This is setting up System.Array*/
5008 g_assert (!mono_class_has_failure (klass->parent)); /*So hitting this assert is a huge problem*/
5009 mcount = mono_class_get_method_count (klass->parent);
5010 for (i = 0; i < mcount; i++) {
5011 MonoMethod *m = klass->parent->methods [i];
5012 if (!strncmp (m->name, "InternalArray__", 15)) {
5014 list = g_list_prepend (list, m);
5017 list = g_list_reverse (list);
5018 generic_array_method_info = (GenericArrayMethodInfo *)mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
5020 for (tmp = list; tmp; tmp = tmp->next) {
5021 const char *mname, *iname;
5023 MonoMethod *m = (MonoMethod *)tmp->data;
5024 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
5025 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
5027 generic_array_method_info [i].array_method = m;
5028 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
5029 iname = "System.Collections.Generic.ICollection`1.";
5030 mname = m->name + 27;
5031 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
5032 iname = "System.Collections.Generic.IEnumerable`1.";
5033 mname = m->name + 27;
5034 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
5035 iname = "System.Collections.Generic.IReadOnlyList`1.";
5036 mname = m->name + strlen (ireadonlylist_prefix);
5037 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
5038 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
5039 mname = m->name + strlen (ireadonlycollection_prefix);
5040 } else if (!strncmp (m->name, "InternalArray__", 15)) {
5041 iname = "System.Collections.Generic.IList`1.";
5042 mname = m->name + 15;
5044 g_assert_not_reached ();
5047 name = (gchar *)mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
5048 strcpy (name, iname);
5049 strcpy (name + strlen (iname), mname);
5050 generic_array_method_info [i].name = name;
5053 /*g_print ("array generic methods: %d\n", count_generic);*/
5055 generic_array_method_num = count_generic;
5057 return generic_array_method_num;
5061 setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos)
5063 MonoGenericContext tmp_context;
5066 tmp_context.class_inst = NULL;
5067 tmp_context.method_inst = mono_class_get_generic_class (iface)->context.class_inst;
5068 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
5070 for (i = 0; i < generic_array_method_num; i++) {
5072 MonoMethod *m = generic_array_method_info [i].array_method;
5073 MonoMethod *inflated;
5075 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
5076 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
5077 methods [pos++] = mono_marshal_get_generic_array_helper (klass, iface, generic_array_method_info [i].name, inflated);
5082 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
5084 int null_length = strlen ("(null)");
5085 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
5086 char *s = (char *)mono_image_alloc (image, len);
5089 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
5090 g_assert (result == len - 1);
5097 * @klass: the class to initialize
5099 * Compute the instance_size, class_size and other infos that cannot be
5100 * computed at mono_class_get() time. Also compute vtable_size if possible.
5101 * Returns TRUE on success or FALSE if there was a problem in loading
5102 * the type (incorrect assemblies, missing assemblies, methods, etc).
5103 * Initializes the following fields in @klass:
5104 * - all the fields initialized by mono_class_init_sizes ()
5109 * LOCKING: Acquires the loader lock.
5112 mono_class_init (MonoClass *klass)
5114 int i, vtable_size = 0, array_method_count = 0;
5115 MonoCachedClassInfo cached_info;
5116 gboolean has_cached_info;
5117 gboolean locked = FALSE;
5118 gboolean ghcimpl = FALSE;
5119 gboolean has_cctor = FALSE;
5120 int first_iface_slot = 0;
5124 /* Double-checking locking pattern */
5125 if (klass->inited || mono_class_has_failure (klass))
5126 return !mono_class_has_failure (klass);
5128 /*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/
5131 * This function can recursively call itself.
5133 GSList *init_list = (GSList *)mono_native_tls_get_value (init_pending_tls_id);
5134 if (g_slist_find (init_list, klass)) {
5135 mono_class_set_type_load_failure (klass, "Recursive type definition detected");
5138 init_list = g_slist_prepend (init_list, klass);
5139 mono_native_tls_set_value (init_pending_tls_id, init_list);
5142 * We want to avoid doing complicated work inside locks, so we compute all the required
5143 * information and write it to @klass inside a lock.
5146 if (mono_verifier_is_enabled_for_class (klass) && !mono_verifier_verify_class (klass)) {
5147 mono_class_set_type_load_failure (klass, "%s", concat_two_strings_with_zero (klass->image, klass->name, klass->image->assembly_name));
5151 if (klass->byval_arg.type == MONO_TYPE_ARRAY || klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5152 MonoClass *element_class = klass->element_class;
5153 if (!element_class->inited)
5154 mono_class_init (element_class);
5155 if (mono_class_set_type_load_failure_causedby_class (klass, element_class, "Could not load array element class"))
5159 mono_stats.initialized_class_count++;
5161 if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic) {
5162 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5164 mono_class_init (gklass);
5165 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic Type Definition failed to init"))
5168 mono_class_setup_interface_id (klass);
5171 if (klass->parent && !klass->parent->inited)
5172 mono_class_init (klass->parent);
5174 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
5176 /* Compute instance size etc. */
5177 init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
5178 if (mono_class_has_failure (klass))
5181 mono_class_setup_supertypes (klass);
5184 initialize_object_slots (klass);
5187 * Initialize the rest of the data without creating a generic vtable if possible.
5188 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5189 * also avoid computing a generic vtable.
5191 if (has_cached_info) {
5193 vtable_size = cached_info.vtable_size;
5194 ghcimpl = cached_info.ghcimpl;
5195 has_cctor = cached_info.has_cctor;
5196 } else if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5197 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5198 * The first slot if for array with.
5200 static int szarray_vtable_size[2] = { 0 };
5202 int slot = MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg) ? 0 : 1;
5205 if (!szarray_vtable_size [slot]) {
5206 mono_class_setup_vtable (klass);
5207 szarray_vtable_size [slot] = klass->vtable_size;
5208 vtable_size = klass->vtable_size;
5210 vtable_size = szarray_vtable_size[slot];
5212 } else if (mono_class_is_ginst (klass) && !MONO_CLASS_IS_INTERFACE (klass)) {
5213 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5215 /* Generic instance case */
5216 ghcimpl = gklass->ghcimpl;
5217 has_cctor = gklass->has_cctor;
5219 mono_class_setup_vtable (gklass);
5220 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to init"))
5223 vtable_size = gklass->vtable_size;
5227 /* ghcimpl is not currently used
5229 if (klass->parent) {
5230 MonoMethod *cmethod = klass->vtable [ghc_slot];
5231 if (cmethod->is_inflated)
5232 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5233 if (cmethod == default_ghc) {
5239 /* C# doesn't allow interfaces to have cctors */
5240 if (!MONO_CLASS_IS_INTERFACE (klass) || klass->image != mono_defaults.corlib) {
5241 MonoMethod *cmethod = NULL;
5243 if (mono_class_is_ginst (klass)) {
5244 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5246 /* Generic instance case */
5247 ghcimpl = gklass->ghcimpl;
5248 has_cctor = gklass->has_cctor;
5249 } else if (klass->type_token && !image_is_dynamic(klass->image)) {
5250 cmethod = find_method_in_metadata (klass, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5251 /* The find_method function ignores the 'flags' argument */
5252 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5255 mono_class_setup_methods (klass);
5256 if (mono_class_has_failure (klass))
5259 int mcount = mono_class_get_method_count (klass);
5260 for (i = 0; i < mcount; ++i) {
5261 MonoMethod *method = klass->methods [i];
5262 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5263 (strcmp (".cctor", method->name) == 0)) {
5273 array_method_count = 3 + (klass->rank > 1? 2: 1);
5275 if (klass->interface_count) {
5276 int count_generic = generic_array_methods (klass);
5277 array_method_count += klass->interface_count * count_generic;
5281 if (klass->parent) {
5282 if (!klass->parent->vtable_size)
5283 mono_class_setup_vtable (klass->parent);
5284 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class vtable failed to initialize"))
5286 g_assert (klass->parent->vtable_size);
5287 first_iface_slot = klass->parent->vtable_size;
5288 if (mono_class_need_stelemref_method (klass))
5293 * Do the actual changes to @klass inside the loader lock
5295 mono_loader_lock ();
5298 if (klass->inited || mono_class_has_failure (klass)) {
5299 mono_loader_unlock ();
5300 /* Somebody might have gotten in before us */
5301 return !mono_class_has_failure (klass);
5304 mono_stats.initialized_class_count++;
5306 if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic)
5307 mono_stats.generic_class_count++;
5309 if (mono_class_is_ginst (klass) || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
5310 klass->nested_classes_inited = TRUE;
5311 klass->ghcimpl = ghcimpl;
5312 klass->has_cctor = has_cctor;
5314 klass->vtable_size = vtable_size;
5315 if (has_cached_info) {
5316 klass->has_finalize = cached_info.has_finalize;
5317 klass->has_finalize_inited = TRUE;
5320 mono_class_set_method_count (klass, array_method_count);
5322 mono_loader_unlock ();
5325 setup_interface_offsets (klass, first_iface_slot, TRUE);
5327 if (mono_security_core_clr_enabled ())
5328 mono_security_core_clr_check_inheritance (klass);
5330 if (mono_class_is_ginst (klass) && !mono_verifier_class_is_valid_generic_instantiation (klass))
5331 mono_class_set_type_load_failure (klass, "Invalid generic instantiation");
5336 init_list = g_slist_remove (init_list, klass);
5337 mono_native_tls_set_value (init_pending_tls_id, init_list);
5339 /* Because of the double-checking locking pattern */
5340 mono_memory_barrier ();
5344 mono_loader_unlock ();
5346 return !mono_class_has_failure (klass);
5350 * mono_class_has_finalizer:
5352 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5356 mono_class_has_finalizer (MonoClass *klass)
5358 gboolean has_finalize = FALSE;
5360 if (klass->has_finalize_inited)
5361 return klass->has_finalize;
5363 /* Interfaces and valuetypes are not supposed to have finalizers */
5364 if (!(MONO_CLASS_IS_INTERFACE (klass) || klass->valuetype)) {
5365 MonoMethod *cmethod = NULL;
5367 if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5368 } else if (mono_class_is_ginst (klass)) {
5369 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5371 has_finalize = mono_class_has_finalizer (gklass);
5372 } else if (klass->parent && klass->parent->has_finalize) {
5373 has_finalize = TRUE;
5375 if (klass->parent) {
5377 * Can't search in metadata for a method named Finalize, because that
5378 * ignores overrides.
5380 mono_class_setup_vtable (klass);
5381 if (mono_class_has_failure (klass))
5384 cmethod = klass->vtable [finalize_slot];
5388 g_assert (klass->vtable_size > finalize_slot);
5390 if (klass->parent) {
5391 if (cmethod->is_inflated)
5392 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5393 if (cmethod != default_finalize)
5394 has_finalize = TRUE;
5400 mono_image_lock (klass->image);
5402 if (!klass->has_finalize_inited) {
5403 klass->has_finalize = has_finalize ? 1 : 0;
5405 mono_memory_barrier ();
5406 klass->has_finalize_inited = TRUE;
5409 mono_image_unlock (klass->image);
5411 return klass->has_finalize;
5415 mono_is_corlib_image (MonoImage *image)
5417 return image == mono_defaults.corlib;
5421 * LOCKING: this assumes the loader lock is held
5424 mono_class_setup_mono_type (MonoClass *klass)
5426 const char *name = klass->name;
5427 const char *nspace = klass->name_space;
5428 gboolean is_corlib = mono_is_corlib_image (klass->image);
5430 klass->this_arg.byref = 1;
5431 klass->this_arg.data.klass = klass;
5432 klass->this_arg.type = MONO_TYPE_CLASS;
5433 klass->byval_arg.data.klass = klass;
5434 klass->byval_arg.type = MONO_TYPE_CLASS;
5436 if (is_corlib && !strcmp (nspace, "System")) {
5437 if (!strcmp (name, "ValueType")) {
5439 * do not set the valuetype bit for System.ValueType.
5440 * klass->valuetype = 1;
5442 klass->blittable = TRUE;
5443 } else if (!strcmp (name, "Enum")) {
5445 * do not set the valuetype bit for System.Enum.
5446 * klass->valuetype = 1;
5448 klass->valuetype = 0;
5449 klass->enumtype = 0;
5450 } else if (!strcmp (name, "Object")) {
5451 klass->byval_arg.type = MONO_TYPE_OBJECT;
5452 klass->this_arg.type = MONO_TYPE_OBJECT;
5453 } else if (!strcmp (name, "String")) {
5454 klass->byval_arg.type = MONO_TYPE_STRING;
5455 klass->this_arg.type = MONO_TYPE_STRING;
5456 } else if (!strcmp (name, "TypedReference")) {
5457 klass->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5458 klass->this_arg.type = MONO_TYPE_TYPEDBYREF;
5462 if (klass->valuetype) {
5463 int t = MONO_TYPE_VALUETYPE;
5465 if (is_corlib && !strcmp (nspace, "System")) {
5468 if (!strcmp (name, "Boolean")) {
5469 t = MONO_TYPE_BOOLEAN;
5470 } else if (!strcmp(name, "Byte")) {
5472 klass->blittable = TRUE;
5476 if (!strcmp (name, "Char")) {
5481 if (!strcmp (name, "Double")) {
5483 klass->blittable = TRUE;
5487 if (!strcmp (name, "Int32")) {
5489 klass->blittable = TRUE;
5490 } else if (!strcmp(name, "Int16")) {
5492 klass->blittable = TRUE;
5493 } else if (!strcmp(name, "Int64")) {
5495 klass->blittable = TRUE;
5496 } else if (!strcmp(name, "IntPtr")) {
5498 klass->blittable = TRUE;
5502 if (!strcmp (name, "Single")) {
5504 klass->blittable = TRUE;
5505 } else if (!strcmp(name, "SByte")) {
5507 klass->blittable = TRUE;
5511 if (!strcmp (name, "UInt32")) {
5513 klass->blittable = TRUE;
5514 } else if (!strcmp(name, "UInt16")) {
5516 klass->blittable = TRUE;
5517 } else if (!strcmp(name, "UInt64")) {
5519 klass->blittable = TRUE;
5520 } else if (!strcmp(name, "UIntPtr")) {
5522 klass->blittable = TRUE;
5526 if (!strcmp (name, "TypedReference")) {
5527 t = MONO_TYPE_TYPEDBYREF;
5528 klass->blittable = TRUE;
5532 if (!strcmp (name, "Void")) {
5540 klass->byval_arg.type = (MonoTypeEnum)t;
5541 klass->this_arg.type = (MonoTypeEnum)t;
5544 if (MONO_CLASS_IS_INTERFACE (klass))
5545 klass->interface_id = mono_get_unique_iid (klass);
5550 * COM initialization is delayed until needed.
5551 * However when a [ComImport] attribute is present on a type it will trigger
5552 * the initialization. This is not a problem unless the BCL being executed
5553 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5556 init_com_from_comimport (MonoClass *klass)
5558 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5559 if (mono_security_core_clr_enabled ()) {
5560 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5561 if (!mono_security_core_clr_determine_platform_image (klass->image)) {
5562 /* but it can not be made available for application (i.e. user code) since all COM calls
5563 * are considered native calls. In this case we fail with a TypeLoadException (just like
5564 * Silverlight 2 does */
5565 mono_class_set_type_load_failure (klass, "");
5570 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5572 #endif /*DISABLE_COM*/
5575 * LOCKING: this assumes the loader lock is held
5578 mono_class_setup_parent (MonoClass *klass, MonoClass *parent)
5580 gboolean system_namespace;
5581 gboolean is_corlib = mono_is_corlib_image (klass->image);
5583 system_namespace = !strcmp (klass->name_space, "System") && is_corlib;
5585 /* if root of the hierarchy */
5586 if (system_namespace && !strcmp (klass->name, "Object")) {
5587 klass->parent = NULL;
5588 klass->instance_size = sizeof (MonoObject);
5591 if (!strcmp (klass->name, "<Module>")) {
5592 klass->parent = NULL;
5593 klass->instance_size = 0;
5597 if (!MONO_CLASS_IS_INTERFACE (klass)) {
5598 /* Imported COM Objects always derive from __ComObject. */
5600 if (MONO_CLASS_IS_IMPORT (klass)) {
5601 init_com_from_comimport (klass);
5602 if (parent == mono_defaults.object_class)
5603 parent = mono_class_get_com_object_class ();
5607 /* set the parent to something useful and safe, but mark the type as broken */
5608 parent = mono_defaults.object_class;
5609 mono_class_set_type_load_failure (klass, "");
5613 klass->parent = parent;
5615 if (mono_class_is_ginst (parent) && !parent->name) {
5617 * If the parent is a generic instance, we may get
5618 * called before it is fully initialized, especially
5619 * before it has its name.
5624 #ifndef DISABLE_REMOTING
5625 klass->marshalbyref = parent->marshalbyref;
5626 klass->contextbound = parent->contextbound;
5629 klass->delegate = parent->delegate;
5631 if (MONO_CLASS_IS_IMPORT (klass) || mono_class_is_com_object (parent))
5632 mono_class_set_is_com_object (klass);
5634 if (system_namespace) {
5635 #ifndef DISABLE_REMOTING
5636 if (klass->name [0] == 'M' && !strcmp (klass->name, "MarshalByRefObject"))
5637 klass->marshalbyref = 1;
5639 if (klass->name [0] == 'C' && !strcmp (klass->name, "ContextBoundObject"))
5640 klass->contextbound = 1;
5642 if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate"))
5643 klass->delegate = 1;
5646 if (klass->parent->enumtype || (mono_is_corlib_image (klass->parent->image) && (strcmp (klass->parent->name, "ValueType") == 0) &&
5647 (strcmp (klass->parent->name_space, "System") == 0)))
5648 klass->valuetype = 1;
5649 if (mono_is_corlib_image (klass->parent->image) && ((strcmp (klass->parent->name, "Enum") == 0) && (strcmp (klass->parent->name_space, "System") == 0))) {
5650 klass->valuetype = klass->enumtype = 1;
5652 /*klass->enumtype = klass->parent->enumtype; */
5654 /* initialize com types if COM interfaces are present */
5656 if (MONO_CLASS_IS_IMPORT (klass))
5657 init_com_from_comimport (klass);
5659 klass->parent = NULL;
5665 * mono_class_setup_supertypes:
5668 * Build the data structure needed to make fast type checks work.
5669 * This currently sets two fields in @class:
5670 * - idepth: distance between @class and System.Object in the type
5672 * - supertypes: array of classes: each element has a class in the hierarchy
5673 * starting from @class up to System.Object
5675 * LOCKING: Acquires the loader lock.
5678 mono_class_setup_supertypes (MonoClass *klass)
5681 MonoClass **supertypes;
5683 mono_atomic_load_acquire (supertypes, MonoClass **, &klass->supertypes);
5687 if (klass->parent && !klass->parent->supertypes)
5688 mono_class_setup_supertypes (klass->parent);
5690 idepth = klass->parent->idepth + 1;
5694 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, idepth);
5695 supertypes = (MonoClass **)mono_class_alloc0 (klass, sizeof (MonoClass *) * ms);
5697 if (klass->parent) {
5698 CHECKED_METADATA_WRITE_PTR ( supertypes [idepth - 1] , klass );
5701 for (supertype_idx = 0; supertype_idx < klass->parent->idepth; supertype_idx++)
5702 CHECKED_METADATA_WRITE_PTR ( supertypes [supertype_idx] , klass->parent->supertypes [supertype_idx] );
5704 CHECKED_METADATA_WRITE_PTR ( supertypes [0] , klass );
5707 mono_memory_barrier ();
5709 mono_loader_lock ();
5710 klass->idepth = idepth;
5711 /* Needed so idepth is visible before supertypes is set */
5712 mono_memory_barrier ();
5713 klass->supertypes = supertypes;
5714 mono_loader_unlock ();
5718 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5720 MonoClass *gtd = (MonoClass*)user_data;
5721 /* Only try to fix generic instances of @gtd */
5722 if (mono_class_get_generic_class (gclass)->container_class != gtd)
5725 /* Check if the generic instance has no parent. */
5726 if (gtd->parent && !gclass->parent)
5727 mono_generic_class_setup_parent (gclass, gtd);
5733 mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char *msg)
5735 mono_class_set_type_load_failure (klass, "%s", msg);
5736 mono_error_set_type_load_class (error, klass, "%s", msg);
5740 * mono_class_create_from_typedef:
5741 * @image: image where the token is valid
5742 * @type_token: typedef token
5743 * @error: used to return any error found while creating the type
5745 * Create the MonoClass* representing the specified type token.
5746 * @type_token must be a TypeDef token.
5748 * FIXME: don't return NULL on failure, just the the caller figure it out.
5751 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5753 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5754 MonoClass *klass, *parent = NULL;
5755 guint32 cols [MONO_TYPEDEF_SIZE];
5756 guint32 cols_next [MONO_TYPEDEF_SIZE];
5757 guint tidx = mono_metadata_token_index (type_token);
5758 MonoGenericContext *context = NULL;
5759 const char *name, *nspace;
5761 MonoClass **interfaces;
5762 guint32 field_last, method_last;
5763 guint32 nesting_tokeen;
5765 mono_error_init (error);
5767 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5768 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5772 mono_loader_lock ();
5774 if ((klass = (MonoClass *)mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5775 mono_loader_unlock ();
5779 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5781 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5782 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5784 if (mono_metadata_has_generic_params (image, type_token)) {
5785 klass = mono_image_alloc0 (image, sizeof (MonoClassGtd));
5786 klass->class_kind = MONO_CLASS_GTD;
5787 classes_size += sizeof (MonoClassGtd);
5790 klass = mono_image_alloc0 (image, sizeof (MonoClassDef));
5791 klass->class_kind = MONO_CLASS_DEF;
5792 classes_size += sizeof (MonoClassDef);
5797 klass->name_space = nspace;
5799 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5801 klass->image = image;
5802 klass->type_token = type_token;
5803 mono_class_set_flags (klass, cols [MONO_TYPEDEF_FLAGS]);
5805 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
5808 * Check whether we're a generic type definition.
5810 if (mono_class_is_gtd (klass)) {
5811 MonoGenericContainer *generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
5812 generic_container->owner.klass = klass;
5813 generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
5814 context = &generic_container->context;
5815 mono_class_set_generic_container (klass, generic_container);
5816 enable_gclass_recording ();
5819 if (cols [MONO_TYPEDEF_EXTENDS]) {
5821 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5823 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5824 /*WARNING: this must satisfy mono_metadata_type_hash*/
5825 klass->this_arg.byref = 1;
5826 klass->this_arg.data.klass = klass;
5827 klass->this_arg.type = MONO_TYPE_CLASS;
5828 klass->byval_arg.data.klass = klass;
5829 klass->byval_arg.type = MONO_TYPE_CLASS;
5831 parent = mono_class_get_checked (image, parent_token, error);
5832 if (parent && context) /* Always inflate */
5833 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5835 if (parent == NULL) {
5836 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5837 goto parent_failure;
5840 for (tmp = parent; tmp; tmp = tmp->parent) {
5842 mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
5843 goto parent_failure;
5845 if (mono_class_is_gtd (klass) && mono_class_is_ginst (tmp) && mono_class_get_generic_class (tmp)->container_class == klass) {
5846 mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
5847 goto parent_failure;
5852 mono_class_setup_parent (klass, parent);
5854 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5855 mono_class_setup_mono_type (klass);
5857 if (mono_class_is_gtd (klass))
5858 disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
5861 * This might access klass->byval_arg for recursion generated by generic constraints,
5862 * so it has to come after setup_mono_type ().
5864 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5865 klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5866 if (!mono_error_ok (error)) {
5867 /*FIXME implement a mono_class_set_failure_from_mono_error */
5868 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5869 mono_loader_unlock ();
5870 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5875 if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5879 if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5883 klass->cast_class = klass->element_class = klass;
5885 if (!klass->enumtype) {
5886 if (!mono_metadata_interfaces_from_typedef_full (
5887 image, type_token, &interfaces, &icount, FALSE, context, error)){
5889 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5890 mono_loader_unlock ();
5891 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5895 /* This is required now that it is possible for more than 2^16 interfaces to exist. */
5896 g_assert(icount <= 65535);
5898 klass->interfaces = interfaces;
5899 klass->interface_count = icount;
5900 klass->interfaces_inited = 1;
5903 /*g_print ("Load class %s\n", name);*/
5906 * Compute the field and method lists
5908 int first_field_idx = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5909 mono_class_set_first_field_idx (klass, first_field_idx);
5910 int first_method_idx = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5911 mono_class_set_first_method_idx (klass, first_method_idx);
5913 if (tt->rows > tidx){
5914 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5915 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5916 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5918 field_last = image->tables [MONO_TABLE_FIELD].rows;
5919 method_last = image->tables [MONO_TABLE_METHOD].rows;
5922 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5923 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5924 mono_class_set_field_count (klass, field_last - first_field_idx);
5925 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5926 mono_class_set_method_count (klass, method_last - first_method_idx);
5928 /* reserve space to store vector pointer in arrays */
5929 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5930 klass->instance_size += 2 * sizeof (gpointer);
5931 g_assert (mono_class_get_field_count (klass) == 0);
5934 if (klass->enumtype) {
5935 MonoType *enum_basetype = mono_class_find_enum_basetype (klass, error);
5936 if (!enum_basetype) {
5937 /*set it to a default value as the whole runtime can't handle this to be null*/
5938 klass->cast_class = klass->element_class = mono_defaults.int32_class;
5939 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5940 mono_loader_unlock ();
5941 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5944 klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
5948 * If we're a generic type definition, load the constraints.
5949 * We must do this after the class has been constructed to make certain recursive scenarios
5952 if (mono_class_is_gtd (klass) && !mono_metadata_load_generic_param_constraints_checked (image, type_token, mono_class_get_generic_container (klass), error)) {
5953 mono_class_set_type_load_failure (klass, "Could not load generic parameter constrains due to %s", mono_error_get_message (error));
5954 mono_loader_unlock ();
5955 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5959 if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5960 if (!strncmp (name, "Vector", 6))
5961 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");
5964 mono_loader_unlock ();
5966 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5971 mono_class_setup_mono_type (klass);
5972 mono_loader_unlock ();
5973 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5977 /** Is klass a Nullable<T> ginst? */
5979 mono_class_is_nullable (MonoClass *klass)
5981 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
5982 return gklass && gklass->container_class == mono_defaults.generic_nullable_class;
5986 /** if klass is T? return T */
5988 mono_class_get_nullable_param (MonoClass *klass)
5990 g_assert (mono_class_is_nullable (klass));
5991 return mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
5995 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5999 MonoGenericClass *gclass = mono_class_get_generic_class (klass);
6001 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
6002 if (!mono_error_ok (&error)) {
6003 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
6004 klass->parent = mono_defaults.object_class;
6005 mono_class_set_type_load_failure (klass, "Parent is a generic type instantiation that failed due to: %s", mono_error_get_message (&error));
6006 mono_error_cleanup (&error);
6010 mono_class_setup_parent (klass, klass->parent);
6012 if (klass->enumtype) {
6013 klass->cast_class = gtd->cast_class;
6014 klass->element_class = gtd->element_class;
6020 * Create the `MonoClass' for an instantiation of a generic type.
6021 * We only do this if we actually need it.
6024 mono_generic_class_get_class (MonoGenericClass *gclass)
6026 MonoClass *klass, *gklass;
6028 if (gclass->cached_class)
6029 return gclass->cached_class;
6031 mono_loader_lock ();
6032 if (gclass->cached_class) {
6033 mono_loader_unlock ();
6034 return gclass->cached_class;
6037 klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClassGenericInst));
6039 gklass = gclass->container_class;
6041 if (record_gclass_instantiation > 0)
6042 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
6044 if (gklass->nested_in) {
6045 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
6046 klass->nested_in = gklass->nested_in;
6049 klass->name = gklass->name;
6050 klass->name_space = gklass->name_space;
6052 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6054 klass->image = gklass->image;
6055 klass->type_token = gklass->type_token;
6057 klass->class_kind = MONO_CLASS_GINST;
6059 ((MonoClassGenericInst*)klass)->generic_class = gclass;
6061 klass->byval_arg.type = MONO_TYPE_GENERICINST;
6062 klass->this_arg.type = klass->byval_arg.type;
6063 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
6064 klass->this_arg.byref = TRUE;
6065 klass->enumtype = gklass->enumtype;
6066 klass->valuetype = gklass->valuetype;
6068 klass->cast_class = klass->element_class = klass;
6070 if (mono_class_is_nullable (klass))
6071 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
6074 * We're not interested in the nested classes of a generic instance.
6075 * We use the generic type definition to look for nested classes.
6078 mono_generic_class_setup_parent (klass, gklass);
6080 if (gclass->is_dynamic) {
6082 * 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.
6083 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
6084 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
6086 if (!gklass->wastypebuilder)
6089 mono_class_setup_supertypes (klass);
6091 if (klass->enumtype) {
6093 * For enums, gklass->fields might not been set, but instance_size etc. is
6094 * already set in mono_reflection_create_internal_class (). For non-enums,
6095 * these will be computed normally in mono_class_layout_fields ().
6097 klass->instance_size = gklass->instance_size;
6098 klass->sizes.class_size = gklass->sizes.class_size;
6099 mono_memory_barrier ();
6100 klass->size_inited = 1;
6104 mono_memory_barrier ();
6105 gclass->cached_class = klass;
6107 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6109 ++class_ginst_count;
6110 inflated_classes_size += sizeof (MonoClassGenericInst);
6112 mono_loader_unlock ();
6118 get_image_for_container (MonoGenericContainer *container)
6121 if (container->is_anonymous) {
6122 result = container->owner.image;
6125 if (container->is_method) {
6126 MonoMethod *method = container->owner.method;
6127 g_assert_checked (method);
6128 klass = method->klass;
6130 klass = container->owner.klass;
6132 g_assert_checked (klass);
6133 result = klass->image;
6140 get_image_for_generic_param (MonoGenericParam *param)
6142 MonoGenericContainer *container = mono_generic_param_owner (param);
6143 g_assert_checked (container);
6144 return get_image_for_container (container);
6147 // Make a string in the designated image consisting of a single integer.
6148 #define INT_STRING_SIZE 16
6150 make_generic_name_string (MonoImage *image, int num)
6152 char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
6153 g_snprintf (name, INT_STRING_SIZE, "%d", num);
6157 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
6158 // pinfo is derived from param by the caller for us.
6160 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
6162 MonoClass *klass, **ptr;
6164 MonoGenericContainer *container = mono_generic_param_owner (param);
6165 g_assert_checked (container);
6167 MonoImage *image = get_image_for_container (container);
6168 gboolean is_mvar = container->is_method;
6169 gboolean is_anonymous = container->is_anonymous;
6171 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassGenericParam));
6172 klass->class_kind = MONO_CLASS_GPARAM;
6173 classes_size += sizeof (MonoClassGenericParam);
6174 ++class_gparam_count;
6177 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
6179 int n = mono_generic_param_num (param);
6180 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
6184 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , "" );
6185 } else if (is_mvar) {
6186 MonoMethod *omethod = container->owner.method;
6187 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
6189 MonoClass *oklass = container->owner.klass;
6190 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
6193 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6195 // Count non-NULL items in pinfo->constraints
6198 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6202 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6203 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
6205 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
6206 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
6208 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
6211 if (count - pos > 0) {
6212 klass->interface_count = count - pos;
6213 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
6214 klass->interfaces_inited = TRUE;
6215 for (i = pos; i < count; i++)
6216 CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
6219 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
6221 klass->inited = TRUE;
6222 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class , klass );
6223 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
6225 klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6226 klass->this_arg.type = klass->byval_arg.type;
6227 CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param , param );
6228 CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
6229 klass->this_arg.byref = TRUE;
6231 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6232 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6234 /*Init these fields to sane values*/
6235 klass->min_align = 1;
6237 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6238 * constrained to, the JIT depends on this.
6240 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6241 mono_memory_barrier ();
6242 klass->size_inited = 1;
6244 mono_class_setup_supertypes (klass);
6246 if (count - pos > 0) {
6247 mono_class_setup_vtable (klass->parent);
6248 if (mono_class_has_failure (klass->parent))
6249 mono_class_set_type_load_failure (klass, "Failed to setup parent interfaces");
6251 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6257 #define FAST_CACHE_SIZE 16
6260 * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6261 * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6262 * we cache the MonoClasses.
6263 * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6264 * LOCKING: Takes the image lock depending on @take_lock.
6267 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6269 int n = mono_generic_param_num (param);
6270 MonoImage *image = get_image_for_generic_param (param);
6271 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6272 MonoClass *klass = NULL;
6277 // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6278 // For high numbers or constraints we have to use pointer hashes.
6279 if (param->gshared_constraint) {
6280 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6283 mono_image_lock (image);
6284 klass = (MonoClass *)g_hash_table_lookup (ht, param);
6286 mono_image_unlock (image);
6291 if (n < FAST_CACHE_SIZE) {
6293 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6295 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6297 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6300 mono_image_lock (image);
6301 klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6303 mono_image_unlock (image);
6310 * LOCKING: Image lock (param->image) must be held
6313 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6315 int n = mono_generic_param_num (param);
6316 MonoImage *image = get_image_for_generic_param (param);
6317 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6321 if (param->gshared_constraint) {
6322 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6324 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6325 mono_memory_barrier ();
6327 image->mvar_cache_constrained = ht;
6329 image->var_cache_constrained = ht;
6331 g_hash_table_insert (ht, param, klass);
6332 } else if (n < FAST_CACHE_SIZE) {
6334 /* Requires locking to avoid droping an already published class */
6335 if (!image->mvar_cache_fast)
6336 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6337 image->mvar_cache_fast [n] = klass;
6339 if (!image->var_cache_fast)
6340 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6341 image->var_cache_fast [n] = klass;
6344 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6346 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6348 ht = g_hash_table_new (NULL, NULL);
6349 mono_memory_barrier ();
6351 image->mvar_cache_slow = ht;
6353 image->var_cache_slow = ht;
6356 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6361 * LOCKING: Acquires the image lock (@image).
6364 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6366 MonoImage *image = get_image_for_generic_param (param);
6367 MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6368 MonoClass *klass, *klass2;
6370 // If a klass already exists for this object and is cached, return it.
6371 if (pinfo) // Non-anonymous
6372 klass = pinfo->pklass;
6374 klass = get_anon_gparam_class (param, TRUE);
6379 // Create a new klass
6380 klass = make_generic_param_class (param, pinfo);
6382 // Now we need to cache the klass we created.
6383 // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6384 // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6385 // and allow our newly-created klass object to just leak.
6386 mono_memory_barrier ();
6388 mono_image_lock (image);
6390 // Here "klass2" refers to the klass potentially created by the other thread.
6391 if (pinfo) // Repeat check from above
6392 klass2 = pinfo->pklass;
6394 klass2 = get_anon_gparam_class (param, FALSE);
6401 pinfo->pklass = klass;
6403 set_anon_gparam_class (param, klass);
6405 mono_image_unlock (image);
6407 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6409 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED); // Alert profiler about botched class create
6411 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6417 * mono_class_from_generic_parameter:
6418 * @param: Parameter to find/construct a class for.
6419 * @arg2: Is ignored.
6420 * @arg3: Is ignored.
6423 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6425 return mono_class_from_generic_parameter_internal (param);
6430 mono_ptr_class_get (MonoType *type)
6433 MonoClass *el_class;
6437 el_class = mono_class_from_mono_type (type);
6438 image = el_class->image;
6440 mono_image_lock (image);
6441 if (image->ptr_cache) {
6442 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6443 mono_image_unlock (image);
6447 mono_image_unlock (image);
6449 result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassPointer));
6451 classes_size += sizeof (MonoClassPointer);
6452 ++class_pointer_count;
6454 result->parent = NULL; /* no parent for PTR types */
6455 result->name_space = el_class->name_space;
6456 name = g_strdup_printf ("%s*", el_class->name);
6457 result->name = mono_image_strdup (image, name);
6458 result->class_kind = MONO_CLASS_POINTER;
6461 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6463 result->image = el_class->image;
6464 result->inited = TRUE;
6465 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6466 result->cast_class = result->element_class = el_class;
6467 result->blittable = TRUE;
6469 result->byval_arg.type = MONO_TYPE_PTR;
6470 result->this_arg.type = result->byval_arg.type;
6471 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6472 result->this_arg.byref = TRUE;
6474 mono_class_setup_supertypes (result);
6476 mono_image_lock (image);
6477 if (image->ptr_cache) {
6479 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6480 mono_image_unlock (image);
6481 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6485 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6487 g_hash_table_insert (image->ptr_cache, el_class, result);
6488 mono_image_unlock (image);
6490 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6496 mono_fnptr_class_get (MonoMethodSignature *sig)
6499 static GHashTable *ptr_hash = NULL;
6501 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6503 mono_loader_lock ();
6506 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6508 if ((result = (MonoClass *)g_hash_table_lookup (ptr_hash, sig))) {
6509 mono_loader_unlock ();
6512 result = g_new0 (MonoClass, 1);
6514 classes_size += sizeof (MonoClassPointer);
6515 ++class_pointer_count;
6517 result->parent = NULL; /* no parent for PTR types */
6518 result->name_space = "System";
6519 result->name = "MonoFNPtrFakeClass";
6520 result->class_kind = MONO_CLASS_POINTER;
6522 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6524 result->image = mono_defaults.corlib; /* need to fix... */
6525 result->inited = TRUE;
6526 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6527 result->cast_class = result->element_class = result;
6528 result->blittable = TRUE;
6530 result->byval_arg.type = MONO_TYPE_FNPTR;
6531 result->this_arg.type = result->byval_arg.type;
6532 result->this_arg.data.method = result->byval_arg.data.method = sig;
6533 result->this_arg.byref = TRUE;
6534 result->blittable = TRUE;
6536 mono_class_setup_supertypes (result);
6538 g_hash_table_insert (ptr_hash, sig, result);
6540 mono_loader_unlock ();
6542 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6548 * mono_class_from_mono_type:
6549 * @type: describes the type to return
6551 * This returns a MonoClass for the specified MonoType, the value is never NULL.
6554 mono_class_from_mono_type (MonoType *type)
6556 switch (type->type) {
6557 case MONO_TYPE_OBJECT:
6558 return type->data.klass? type->data.klass: mono_defaults.object_class;
6559 case MONO_TYPE_VOID:
6560 return type->data.klass? type->data.klass: mono_defaults.void_class;
6561 case MONO_TYPE_BOOLEAN:
6562 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6563 case MONO_TYPE_CHAR:
6564 return type->data.klass? type->data.klass: mono_defaults.char_class;
6566 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6568 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6570 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6572 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6574 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6576 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6578 return type->data.klass? type->data.klass: mono_defaults.int_class;
6580 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6582 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6584 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6586 return type->data.klass? type->data.klass: mono_defaults.single_class;
6588 return type->data.klass? type->data.klass: mono_defaults.double_class;
6589 case MONO_TYPE_STRING:
6590 return type->data.klass? type->data.klass: mono_defaults.string_class;
6591 case MONO_TYPE_TYPEDBYREF:
6592 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6593 case MONO_TYPE_ARRAY:
6594 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6596 return mono_ptr_class_get (type->data.type);
6597 case MONO_TYPE_FNPTR:
6598 return mono_fnptr_class_get (type->data.method);
6599 case MONO_TYPE_SZARRAY:
6600 return mono_array_class_get (type->data.klass, 1);
6601 case MONO_TYPE_CLASS:
6602 case MONO_TYPE_VALUETYPE:
6603 return type->data.klass;
6604 case MONO_TYPE_GENERICINST:
6605 return mono_generic_class_get_class (type->data.generic_class);
6606 case MONO_TYPE_MVAR:
6608 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6610 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6611 g_assert_not_reached ();
6614 // Yes, this returns NULL, even if it is documented as not doing so, but there
6615 // is no way for the code to make it this far, due to the assert above.
6620 * mono_type_retrieve_from_typespec
6621 * @image: context where the image is created
6622 * @type_spec: typespec token
6623 * @context: the generic context used to evaluate generic instantiations in
6626 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6628 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6630 *did_inflate = FALSE;
6635 if (context && (context->class_inst || context->method_inst)) {
6636 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6638 if (!mono_error_ok (error)) {
6644 *did_inflate = TRUE;
6651 * mono_class_create_from_typespec
6652 * @image: context where the image is created
6653 * @type_spec: typespec token
6654 * @context: the generic context used to evaluate generic instantiations in
6657 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6660 gboolean inflated = FALSE;
6661 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6662 return_val_if_nok (error, NULL);
6663 ret = mono_class_from_mono_type (t);
6665 mono_metadata_free_type (t);
6670 * mono_bounded_array_class_get:
6671 * @element_class: element class
6672 * @rank: the dimension of the array class
6673 * @bounded: whenever the array has non-zero bounds
6675 * Returns: A class object describing the array with element type @element_type and
6679 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6683 MonoClass *parent = NULL;
6684 GSList *list, *rootlist = NULL;
6688 g_assert (rank <= 255);
6691 /* bounded only matters for one-dimensional arrays */
6694 image = eclass->image;
6696 if (rank == 1 && !bounded) {
6698 * This case is very frequent not just during compilation because of calls
6699 * from mono_class_from_mono_type (), mono_array_new (),
6700 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6702 mono_os_mutex_lock (&image->szarray_cache_lock);
6703 if (!image->szarray_cache)
6704 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6705 klass = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6706 mono_os_mutex_unlock (&image->szarray_cache_lock);
6710 mono_loader_lock ();
6712 mono_loader_lock ();
6714 if (!image->array_cache)
6715 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6717 if ((rootlist = list = (GSList *)g_hash_table_lookup (image->array_cache, eclass))) {
6718 for (; list; list = list->next) {
6719 klass = (MonoClass *)list->data;
6720 if ((klass->rank == rank) && (klass->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6721 mono_loader_unlock ();
6728 parent = mono_defaults.array_class;
6729 if (!parent->inited)
6730 mono_class_init (parent);
6732 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassArray));
6734 klass->image = image;
6735 klass->name_space = eclass->name_space;
6736 klass->class_kind = MONO_CLASS_ARRAY;
6738 nsize = strlen (eclass->name);
6739 name = (char *)g_malloc (nsize + 2 + rank + 1);
6740 memcpy (name, eclass->name, nsize);
6743 memset (name + nsize + 1, ',', rank - 1);
6745 name [nsize + rank] = '*';
6746 name [nsize + rank + bounded] = ']';
6747 name [nsize + rank + bounded + 1] = 0;
6748 klass->name = mono_image_strdup (image, name);
6751 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6753 classes_size += sizeof (MonoClassArray);
6754 ++class_array_count;
6756 klass->type_token = 0;
6757 klass->parent = parent;
6758 klass->instance_size = mono_class_instance_size (klass->parent);
6760 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6761 /*Arrays of those two types are invalid.*/
6762 MonoError prepared_error;
6763 mono_error_init (&prepared_error);
6764 mono_error_set_invalid_program (&prepared_error, "Arrays of void or System.TypedReference types are invalid.");
6765 mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6766 mono_error_cleanup (&prepared_error);
6767 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6768 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6769 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6770 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6772 /* element_size -1 is ok as this is not an instantitable type*/
6773 klass->sizes.element_size = -1;
6775 klass->sizes.element_size = mono_class_array_element_size (eclass);
6777 mono_class_setup_supertypes (klass);
6779 if (mono_class_is_ginst (eclass))
6780 mono_class_init (eclass);
6781 if (!eclass->size_inited)
6782 mono_class_setup_fields (eclass);
6783 mono_class_set_type_load_failure_causedby_class (klass, eclass, "Could not load array element type");
6784 /*FIXME we fail the array type, but we have to let other fields be set.*/
6786 klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6790 if (eclass->enumtype)
6791 klass->cast_class = eclass->element_class;
6793 klass->cast_class = eclass;
6795 switch (klass->cast_class->byval_arg.type) {
6797 klass->cast_class = mono_defaults.byte_class;
6800 klass->cast_class = mono_defaults.int16_class;
6803 #if SIZEOF_VOID_P == 4
6807 klass->cast_class = mono_defaults.int32_class;
6810 #if SIZEOF_VOID_P == 8
6814 klass->cast_class = mono_defaults.int64_class;
6820 klass->element_class = eclass;
6822 if ((rank > 1) || bounded) {
6823 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6824 klass->byval_arg.type = MONO_TYPE_ARRAY;
6825 klass->byval_arg.data.array = at;
6826 at->eklass = eclass;
6828 /* FIXME: complete.... */
6830 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6831 klass->byval_arg.data.klass = eclass;
6833 klass->this_arg = klass->byval_arg;
6834 klass->this_arg.byref = 1;
6836 //WTF was this? it's wrong
6837 // klass->generic_container = eclass->generic_container;
6839 if (rank == 1 && !bounded) {
6840 MonoClass *prev_class;
6842 mono_os_mutex_lock (&image->szarray_cache_lock);
6843 prev_class = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6845 /* Someone got in before us */
6848 g_hash_table_insert (image->szarray_cache, eclass, klass);
6849 mono_os_mutex_unlock (&image->szarray_cache_lock);
6851 list = g_slist_append (rootlist, klass);
6852 g_hash_table_insert (image->array_cache, eclass, list);
6855 mono_loader_unlock ();
6857 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6863 * mono_array_class_get:
6864 * @element_class: element class
6865 * @rank: the dimension of the array class
6867 * Returns: A class object describing the array with element type @element_type and
6871 mono_array_class_get (MonoClass *eclass, guint32 rank)
6873 return mono_bounded_array_class_get (eclass, rank, FALSE);
6877 * mono_class_instance_size:
6880 * Use to get the size of a class in bytes.
6882 * Returns: The size of an object instance
6885 mono_class_instance_size (MonoClass *klass)
6887 if (!klass->size_inited)
6888 mono_class_init (klass);
6890 return klass->instance_size;
6894 * mono_class_min_align:
6897 * Use to get the computed minimum alignment requirements for the specified class.
6899 * Returns: minimum alignment requirements
6902 mono_class_min_align (MonoClass *klass)
6904 if (!klass->size_inited)
6905 mono_class_init (klass);
6907 return klass->min_align;
6911 * mono_class_value_size:
6914 * This function is used for value types, and return the
6915 * space and the alignment to store that kind of value object.
6917 * Returns: the size of a value of kind @klass
6920 mono_class_value_size (MonoClass *klass, guint32 *align)
6924 /* fixme: check disable, because we still have external revereces to
6925 * mscorlib and Dummy Objects
6927 /*g_assert (klass->valuetype);*/
6929 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6932 *align = klass->min_align;
6938 * mono_class_data_size:
6941 * Returns: The size of the static class data
6944 mono_class_data_size (MonoClass *klass)
6947 mono_class_init (klass);
6948 /* This can happen with dynamically created types */
6949 if (!klass->fields_inited)
6950 mono_class_setup_fields (klass);
6952 /* in arrays, sizes.class_size is unioned with element_size
6953 * and arrays have no static fields
6957 return klass->sizes.class_size;
6961 * Auxiliary routine to mono_class_get_field
6963 * Takes a field index instead of a field token.
6965 static MonoClassField *
6966 mono_class_get_field_idx (MonoClass *klass, int idx)
6968 mono_class_setup_fields (klass);
6969 if (mono_class_has_failure (klass))
6973 int first_field_idx = mono_class_get_first_field_idx (klass);
6974 int fcount = mono_class_get_field_count (klass);
6975 if (klass->image->uncompressed_metadata) {
6977 * first_field_idx points to the FieldPtr table, while idx points into the
6978 * Field table, so we have to do a search.
6980 /*FIXME this is broken for types with multiple fields with the same name.*/
6981 const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6984 for (i = 0; i < fcount; ++i)
6985 if (mono_field_get_name (&klass->fields [i]) == name)
6986 return &klass->fields [i];
6987 g_assert_not_reached ();
6990 if ((idx >= first_field_idx) && (idx < first_field_idx + fcount)){
6991 return &klass->fields [idx - first_field_idx];
6995 klass = klass->parent;
7001 * mono_class_get_field:
7002 * @class: the class to lookup the field.
7003 * @field_token: the field token
7005 * Returns: A MonoClassField representing the type and offset of
7006 * the field, or a NULL value if the field does not belong to this
7010 mono_class_get_field (MonoClass *klass, guint32 field_token)
7012 int idx = mono_metadata_token_index (field_token);
7014 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
7016 return mono_class_get_field_idx (klass, idx - 1);
7020 * mono_class_get_field_from_name:
7021 * @klass: the class to lookup the field.
7022 * @name: the field name
7024 * Search the class @klass and it's parents for a field with the name @name.
7026 * Returns: The MonoClassField pointer of the named field or NULL
7029 mono_class_get_field_from_name (MonoClass *klass, const char *name)
7031 return mono_class_get_field_from_name_full (klass, name, NULL);
7035 * mono_class_get_field_from_name_full:
7036 * @klass: the class to lookup the field.
7037 * @name: the field name
7038 * @type: the type of the fields. This optional.
7040 * Search the class @klass and it's parents for a field with the name @name and type @type.
7042 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
7043 * of its generic type definition.
7045 * Returns: The MonoClassField pointer of the named field or NULL
7048 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
7052 mono_class_setup_fields (klass);
7053 if (mono_class_has_failure (klass))
7057 int fcount = mono_class_get_field_count (klass);
7058 for (i = 0; i < fcount; ++i) {
7059 MonoClassField *field = &klass->fields [i];
7061 if (strcmp (name, mono_field_get_name (field)) != 0)
7065 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
7066 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
7071 klass = klass->parent;
7077 * mono_class_get_field_token:
7078 * @field: the field we need the token of
7080 * Get the token of a field. Note that the tokesn is only valid for the image
7081 * the field was loaded from. Don't use this function for fields in dynamic types.
7083 * Returns: The token representing the field in the image it was loaded from.
7086 mono_class_get_field_token (MonoClassField *field)
7088 MonoClass *klass = field->parent;
7091 mono_class_setup_fields (klass);
7096 int first_field_idx = mono_class_get_first_field_idx (klass);
7097 int fcount = mono_class_get_field_count (klass);
7098 for (i = 0; i < fcount; ++i) {
7099 if (&klass->fields [i] == field) {
7100 int idx = first_field_idx + i + 1;
7102 if (klass->image->uncompressed_metadata)
7103 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
7104 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
7107 klass = klass->parent;
7110 g_assert_not_reached ();
7115 mono_field_get_index (MonoClassField *field)
7117 int index = field - field->parent->fields;
7118 g_assert (index >= 0 && index < mono_class_get_field_count (field->parent));
7124 * mono_class_get_field_default_value:
7126 * Return the default value of the field as a pointer into the metadata blob.
7129 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
7132 guint32 constant_cols [MONO_CONSTANT_SIZE];
7134 MonoClass *klass = field->parent;
7136 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7138 if (!klass->ext || !klass->ext->field_def_values) {
7139 MonoFieldDefaultValue *def_values;
7141 mono_class_alloc_ext (klass);
7143 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
7145 mono_image_lock (klass->image);
7146 mono_memory_barrier ();
7147 if (!klass->ext->field_def_values)
7148 klass->ext->field_def_values = def_values;
7149 mono_image_unlock (klass->image);
7152 field_index = mono_field_get_index (field);
7154 if (!klass->ext->field_def_values [field_index].data) {
7155 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7159 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7161 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7162 klass->ext->field_def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7163 klass->ext->field_def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7166 *def_type = klass->ext->field_def_values [field_index].def_type;
7167 return klass->ext->field_def_values [field_index].data;
7171 mono_property_get_index (MonoProperty *prop)
7173 int index = prop - prop->parent->ext->properties;
7175 g_assert (index >= 0 && index < prop->parent->ext->property.count);
7181 * mono_class_get_property_default_value:
7183 * Return the default value of the field as a pointer into the metadata blob.
7186 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7189 guint32 constant_cols [MONO_CONSTANT_SIZE];
7190 MonoClass *klass = property->parent;
7192 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7194 * We don't cache here because it is not used by C# so it's quite rare, but
7195 * we still do the lookup in klass->ext because that is where the data
7196 * is stored for dynamic assemblies.
7199 if (image_is_dynamic (klass->image)) {
7200 int prop_index = mono_property_get_index (property);
7201 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
7202 *def_type = klass->ext->prop_def_values [prop_index].def_type;
7203 return klass->ext->prop_def_values [prop_index].data;
7207 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7211 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7212 *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7213 return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7217 mono_class_get_event_token (MonoEvent *event)
7219 MonoClass *klass = event->parent;
7224 for (i = 0; i < klass->ext->event.count; ++i) {
7225 if (&klass->ext->events [i] == event)
7226 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
7229 klass = klass->parent;
7232 g_assert_not_reached ();
7237 * mono_class_get_property_from_name:
7239 * @name: name of the property to lookup in the specified class
7241 * Use this method to lookup a property in a class
7242 * Returns: the MonoProperty with the given name, or NULL if the property
7243 * does not exist on the @klass.
7246 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7250 gpointer iter = NULL;
7251 while ((p = mono_class_get_properties (klass, &iter))) {
7252 if (! strcmp (name, p->name))
7255 klass = klass->parent;
7261 * mono_class_get_property_token:
7262 * @prop: MonoProperty to query
7264 * Returns: The ECMA token for the specified property.
7267 mono_class_get_property_token (MonoProperty *prop)
7269 MonoClass *klass = prop->parent;
7273 gpointer iter = NULL;
7274 while ((p = mono_class_get_properties (klass, &iter))) {
7275 if (&klass->ext->properties [i] == prop)
7276 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
7280 klass = klass->parent;
7283 g_assert_not_reached ();
7288 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7290 const char *name, *nspace;
7291 if (image_is_dynamic (image))
7292 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7294 switch (type_token & 0xff000000){
7295 case MONO_TOKEN_TYPE_DEF: {
7296 guint32 cols [MONO_TYPEDEF_SIZE];
7297 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7298 guint tidx = mono_metadata_token_index (type_token);
7300 if (tidx > tt->rows)
7301 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7303 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7304 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7305 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7306 if (strlen (nspace) == 0)
7307 return g_strdup_printf ("%s", name);
7309 return g_strdup_printf ("%s.%s", nspace, name);
7312 case MONO_TOKEN_TYPE_REF: {
7314 guint32 cols [MONO_TYPEREF_SIZE];
7315 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7316 guint tidx = mono_metadata_token_index (type_token);
7319 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7321 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7322 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7323 mono_error_cleanup (&error);
7327 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7328 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7329 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7330 if (strlen (nspace) == 0)
7331 return g_strdup_printf ("%s", name);
7333 return g_strdup_printf ("%s.%s", nspace, name);
7336 case MONO_TOKEN_TYPE_SPEC:
7337 return g_strdup_printf ("Typespec 0x%08x", type_token);
7339 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7344 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7346 if (image_is_dynamic (image))
7347 return g_strdup_printf ("DynamicAssembly %s", image->name);
7349 switch (type_token & 0xff000000){
7350 case MONO_TOKEN_TYPE_DEF:
7351 if (image->assembly)
7352 return mono_stringify_assembly_name (&image->assembly->aname);
7353 else if (image->assembly_name)
7354 return g_strdup (image->assembly_name);
7355 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7356 case MONO_TOKEN_TYPE_REF: {
7358 MonoAssemblyName aname;
7359 guint32 cols [MONO_TYPEREF_SIZE];
7360 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7361 guint32 idx = mono_metadata_token_index (type_token);
7364 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7366 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7367 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7368 mono_error_cleanup (&error);
7371 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7373 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7374 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7375 case MONO_RESOLUTION_SCOPE_MODULE:
7377 return g_strdup ("");
7378 case MONO_RESOLUTION_SCOPE_MODULEREF:
7380 return g_strdup ("");
7381 case MONO_RESOLUTION_SCOPE_TYPEREF:
7383 return g_strdup ("");
7384 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7385 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7386 return mono_stringify_assembly_name (&aname);
7388 g_assert_not_reached ();
7392 case MONO_TOKEN_TYPE_SPEC:
7394 return g_strdup ("");
7396 g_assert_not_reached ();
7403 * mono_class_get_full:
7404 * @image: the image where the class resides
7405 * @type_token: the token for the class
7406 * @context: the generic context used to evaluate generic instantiations in
7407 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7409 * Returns: The MonoClass that represents @type_token in @image
7412 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7416 klass = mono_class_get_checked (image, type_token, &error);
7418 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7419 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7421 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7427 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7431 mono_error_init (error);
7432 klass = mono_class_get_checked (image, type_token, error);
7434 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7435 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7440 * mono_class_get_checked:
7441 * @image: the image where the class resides
7442 * @type_token: the token for the class
7443 * @error: error object to return any error
7445 * Returns: The MonoClass that represents @type_token in @image, or NULL on error.
7448 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7450 MonoClass *klass = NULL;
7452 mono_error_init (error);
7454 if (image_is_dynamic (image)) {
7455 int table = mono_metadata_token_table (type_token);
7457 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7458 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7461 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
7465 switch (type_token & 0xff000000){
7466 case MONO_TOKEN_TYPE_DEF:
7467 klass = mono_class_create_from_typedef (image, type_token, error);
7469 case MONO_TOKEN_TYPE_REF:
7470 klass = mono_class_from_typeref_checked (image, type_token, error);
7472 case MONO_TOKEN_TYPE_SPEC:
7473 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7476 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7480 /* Generic case, should be avoided for when a better error is possible. */
7481 if (!klass && mono_error_ok (error)) {
7482 char *name = mono_class_name_from_token (image, type_token);
7483 char *assembly = mono_assembly_name_from_token (image, type_token);
7484 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7492 * mono_type_get_checked:
7493 * @image: the image where the type resides
7494 * @type_token: the token for the type
7495 * @context: the generic context used to evaluate generic instantiations in
7496 * @error: Error handling context
7498 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7500 * Returns: The MonoType that represents @type_token in @image
7503 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7505 MonoType *type = NULL;
7506 gboolean inflated = FALSE;
7508 mono_error_init (error);
7510 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7511 if (image_is_dynamic (image)) {
7512 MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
7513 return_val_if_nok (error, NULL);
7514 return mono_class_get_type (klass);
7517 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7518 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7525 return mono_class_get_type (klass);
7528 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7535 MonoType *tmp = type;
7536 type = mono_class_get_type (mono_class_from_mono_type (type));
7537 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7538 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7539 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7541 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7543 if (type->type != tmp->type)
7546 mono_metadata_free_type (tmp);
7553 * @image: image where the class token will be looked up.
7554 * @type_token: a type token from the image
7556 * Returns the MonoClass with the given @type_token on the @image
7559 mono_class_get (MonoImage *image, guint32 type_token)
7561 return mono_class_get_full (image, type_token, NULL);
7565 * mono_image_init_name_cache:
7567 * Initializes the class name cache stored in image->name_cache.
7569 * LOCKING: Acquires the corresponding image lock.
7572 mono_image_init_name_cache (MonoImage *image)
7574 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7575 guint32 cols [MONO_TYPEDEF_SIZE];
7578 guint32 i, visib, nspace_index;
7579 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7581 if (image->name_cache)
7584 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7586 if (image_is_dynamic (image)) {
7587 mono_image_lock (image);
7588 if (image->name_cache) {
7589 /* Somebody initialized it before us */
7590 g_hash_table_destroy (the_name_cache);
7592 mono_atomic_store_release (&image->name_cache, the_name_cache);
7594 mono_image_unlock (image);
7598 /* Temporary hash table to avoid lookups in the nspace_table */
7599 name_cache2 = g_hash_table_new (NULL, NULL);
7601 for (i = 1; i <= t->rows; ++i) {
7602 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7603 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7605 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7606 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7608 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7610 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7611 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7613 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7614 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7615 if (!nspace_table) {
7616 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7617 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7618 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7621 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7624 /* Load type names from EXPORTEDTYPES table */
7626 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7627 guint32 cols [MONO_EXP_TYPE_SIZE];
7630 for (i = 0; i < t->rows; ++i) {
7631 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7633 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7634 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7638 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7639 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7641 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7642 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7643 if (!nspace_table) {
7644 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7645 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7646 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7649 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7653 g_hash_table_destroy (name_cache2);
7655 mono_image_lock (image);
7656 if (image->name_cache) {
7657 /* Somebody initialized it before us */
7658 g_hash_table_destroy (the_name_cache);
7660 mono_atomic_store_release (&image->name_cache, the_name_cache);
7662 mono_image_unlock (image);
7665 /*FIXME Only dynamic assemblies should allow this operation.*/
7667 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7668 const char *name, guint32 index)
7670 GHashTable *nspace_table;
7671 GHashTable *name_cache;
7674 mono_image_init_name_cache (image);
7675 mono_image_lock (image);
7677 name_cache = image->name_cache;
7678 if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7679 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7680 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7683 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7684 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7686 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7688 mono_image_unlock (image);
7697 find_nocase (gpointer key, gpointer value, gpointer user_data)
7699 char *name = (char*)key;
7700 FindUserData *data = (FindUserData*)user_data;
7702 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7703 data->value = value;
7707 * mono_class_from_name_case:
7708 * @image: The MonoImage where the type is looked up in
7709 * @name_space: the type namespace
7710 * @name: the type short name.
7711 * @deprecated: use the mono_class_from_name_case_checked variant instead.
7713 * Obtains a MonoClass with a given namespace and a given name which
7714 * is located in the given MonoImage. The namespace and name
7715 * lookups are case insensitive.
7718 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7721 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7722 mono_error_cleanup (&error);
7728 * mono_class_from_name_case:
7729 * @image: The MonoImage where the type is looked up in
7730 * @name_space: the type namespace
7731 * @name: the type short name.
7734 * Obtains a MonoClass with a given namespace and a given name which
7735 * is located in the given MonoImage. The namespace and name
7736 * lookups are case insensitive.
7738 * Returns: The MonoClass if the given namespace and name were found, or NULL if it
7739 * was not found. The @error object will contain information about the problem
7743 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7745 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7746 guint32 cols [MONO_TYPEDEF_SIZE];
7751 mono_error_init (error);
7753 if (image_is_dynamic (image)) {
7755 FindUserData user_data;
7757 mono_image_init_name_cache (image);
7758 mono_image_lock (image);
7760 user_data.key = name_space;
7761 user_data.value = NULL;
7762 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7764 if (user_data.value) {
7765 GHashTable *nspace_table = (GHashTable*)user_data.value;
7767 user_data.key = name;
7768 user_data.value = NULL;
7770 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7772 if (user_data.value)
7773 token = GPOINTER_TO_UINT (user_data.value);
7776 mono_image_unlock (image);
7779 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7785 /* add a cache if needed */
7786 for (i = 1; i <= t->rows; ++i) {
7787 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7788 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7790 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7791 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7793 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7795 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7796 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7797 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7798 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7804 return_nested_in (MonoClass *klass, char *nested)
7807 char *s = strchr (nested, '/');
7808 gpointer iter = NULL;
7815 while ((found = mono_class_get_nested_types (klass, &iter))) {
7816 if (strcmp (found->name, nested) == 0) {
7818 return return_nested_in (found, s);
7826 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7828 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7829 MonoImage *file_image;
7833 mono_error_init (error);
7836 * The EXPORTEDTYPES table only contains public types, so have to search the
7838 * Note: image->modules contains the contents of the MODULEREF table, while
7839 * the real module list is in the FILE table.
7841 for (i = 0; i < file_table->rows; i++) {
7842 guint32 cols [MONO_FILE_SIZE];
7843 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7844 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7847 file_image = mono_image_load_file_for_image_checked (image, i + 1, error);
7849 klass = mono_class_from_name_checked (file_image, name_space, name, error);
7850 if (klass || !is_ok (error))
7859 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7861 GHashTable *nspace_table;
7862 MonoImage *loaded_image;
7869 mono_error_init (error);
7871 // Checking visited images avoids stack overflows when cyclic references exist.
7872 if (g_hash_table_lookup (visited_images, image))
7875 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7877 if ((nested = strchr (name, '/'))) {
7878 int pos = nested - name;
7879 int len = strlen (name);
7882 memcpy (buf, name, len + 1);
7884 nested = buf + pos + 1;
7888 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7889 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7890 gboolean res = get_class_from_name (image, name_space, name, &klass);
7893 klass = search_modules (image, name_space, name, error);
7898 return klass ? return_nested_in (klass, nested) : NULL;
7904 mono_image_init_name_cache (image);
7905 mono_image_lock (image);
7907 nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7910 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7912 mono_image_unlock (image);
7914 if (!token && image_is_dynamic (image) && image->modules) {
7915 /* Search modules as well */
7916 for (i = 0; i < image->module_count; ++i) {
7917 MonoImage *module = image->modules [i];
7919 klass = mono_class_from_name_checked (module, name_space, name, error);
7920 if (klass || !is_ok (error))
7926 klass = search_modules (image, name_space, name, error);
7927 if (klass || !is_ok (error))
7932 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7933 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7934 guint32 cols [MONO_EXP_TYPE_SIZE];
7937 idx = mono_metadata_token_index (token);
7939 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7941 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7942 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7943 loaded_image = mono_assembly_load_module_checked (image->assembly, impl >> MONO_IMPLEMENTATION_BITS, error);
7946 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7948 return klass ? return_nested_in (klass, nested) : NULL;
7950 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7951 guint32 assembly_idx;
7953 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7955 mono_assembly_load_reference (image, assembly_idx - 1);
7956 g_assert (image->references [assembly_idx - 1]);
7957 if (image->references [assembly_idx - 1] == (gpointer)-1)
7959 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
7961 return klass ? return_nested_in (klass, nested) : NULL;
7964 g_assert_not_reached ();
7968 token = MONO_TOKEN_TYPE_DEF | token;
7970 klass = mono_class_get_checked (image, token, error);
7972 return return_nested_in (klass, nested);
7977 * mono_class_from_name_checked:
7978 * @image: The MonoImage where the type is looked up in
7979 * @name_space: the type namespace
7980 * @name: the type short name.
7982 * Obtains a MonoClass with a given namespace and a given name which
7983 * is located in the given MonoImage.
7985 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
7986 * set if the class was not found or it will return NULL and set the error if there was a loading error.
7989 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7992 GHashTable *visited_images;
7994 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7996 klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
7998 g_hash_table_destroy (visited_images);
8004 * mono_class_from_name:
8005 * @image: The MonoImage where the type is looked up in
8006 * @name_space: the type namespace
8007 * @name: the type short name.
8009 * Obtains a MonoClass with a given namespace and a given name which
8010 * is located in the given MonoImage.
8012 * To reference nested classes, use the "/" character as a separator.
8013 * For example use "Foo/Bar" to reference the class Bar that is nested
8014 * inside Foo, like this: "class Foo { class Bar {} }".
8017 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
8022 klass = mono_class_from_name_checked (image, name_space, name, &error);
8023 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
8029 * mono_class_load_from_name:
8030 * @image: The MonoImage where the type is looked up in
8031 * @name_space: the type namespace
8032 * @name: the type short name.
8034 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
8035 * This function should be used by the runtime for critical types to which there's no way to recover but crash
8036 * If they are missing. Thing of System.Object or System.String.
8039 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
8044 klass = mono_class_from_name_checked (image, name_space, name, &error);
8046 g_error ("Runtime critical type %s.%s not found", name_space, name);
8047 if (!mono_error_ok (&error))
8048 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8053 * mono_class_try_load_from_name:
8054 * @image: The MonoImage where the type is looked up in
8055 * @name_space: the type namespace
8056 * @name: the type short name.
8058 * This function tries to load a type, returning the class was found or NULL otherwise.
8059 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
8061 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
8062 * a type that we would otherwise assume to be available but was not due some error.
8066 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
8071 klass = mono_class_from_name_checked (image, name_space, name, &error);
8072 if (!mono_error_ok (&error))
8073 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8079 * mono_class_is_subclass_of:
8080 * @klass: class to probe if it is a subclass of another one
8081 * @klassc: the class we suspect is the base class
8082 * @check_interfaces: whether we should perform interface checks
8084 * This method determines whether @klass is a subclass of @klassc.
8086 * If the @check_interfaces flag is set, then if @klassc is an interface
8087 * this method return TRUE if the @klass implements the interface or
8088 * if @klass is an interface, if one of its base classes is @klass.
8090 * If @check_interfaces is false then, then if @klass is not an interface
8091 * then it returns TRUE if the @klass is a subclass of @klassc.
8093 * if @klass is an interface and @klassc is System.Object, then this function
8098 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
8099 gboolean check_interfaces)
8101 /* FIXME test for interfaces with variant generic arguments */
8102 mono_class_init (klass);
8103 mono_class_init (klassc);
8105 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
8106 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
8108 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
8111 for (i = 0; i < klass->interface_count; i ++) {
8112 MonoClass *ic = klass->interfaces [i];
8117 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
8122 * MS.NET thinks interfaces are a subclass of Object, so we think it as
8125 if (klassc == mono_defaults.object_class)
8132 mono_type_is_generic_argument (MonoType *type)
8134 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
8138 mono_class_has_variant_generic_params (MonoClass *klass)
8141 MonoGenericContainer *container;
8143 if (!mono_class_is_ginst (klass))
8146 container = mono_class_get_generic_container (mono_class_get_generic_class (klass)->container_class);
8148 for (i = 0; i < container->type_argc; ++i)
8149 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8156 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8158 if (target == candidate)
8161 if (check_for_reference_conv &&
8162 mono_type_is_generic_argument (&target->byval_arg) &&
8163 mono_type_is_generic_argument (&candidate->byval_arg)) {
8164 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8165 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8167 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8170 if (!mono_class_is_assignable_from (target, candidate))
8176 * @container the generic container from the GTD
8177 * @klass: the class to be assigned to
8178 * @oklass: the source class
8180 * Both @klass and @oklass must be instances of the same generic interface.
8182 * Returns: TRUE if @klass can be assigned to a @klass variable
8185 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8188 MonoType **klass_argv, **oklass_argv;
8189 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8190 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8192 if (klass == oklass)
8195 /*Viable candidates are instances of the same generic interface*/
8196 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8199 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8200 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8202 for (j = 0; j < container->type_argc; ++j) {
8203 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8204 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8206 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8210 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8211 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8213 if (param1_class != param2_class) {
8214 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8215 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8217 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8218 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8228 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8230 MonoGenericParam *gparam, *ogparam;
8231 MonoGenericParamInfo *tinfo, *cinfo;
8232 MonoClass **candidate_class;
8233 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8236 if (target == candidate)
8238 if (target->byval_arg.type != candidate->byval_arg.type)
8241 gparam = target->byval_arg.data.generic_param;
8242 ogparam = candidate->byval_arg.data.generic_param;
8243 tinfo = mono_generic_param_info (gparam);
8244 cinfo = mono_generic_param_info (ogparam);
8246 class_constraint_satisfied = FALSE;
8247 valuetype_constraint_satisfied = FALSE;
8249 /*candidate must have a super set of target's special constraints*/
8250 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8251 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8253 if (cinfo->constraints) {
8254 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8255 MonoClass *cc = *candidate_class;
8257 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8258 class_constraint_satisfied = TRUE;
8259 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8260 valuetype_constraint_satisfied = TRUE;
8263 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8264 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8266 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8268 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8270 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8271 valuetype_constraint_satisfied)) {
8276 /*candidate type constraints must be a superset of target's*/
8277 if (tinfo->constraints) {
8278 MonoClass **target_class;
8279 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8280 MonoClass *tc = *target_class;
8283 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8284 * check it's constraints since it satisfy the constraint by itself.
8286 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8289 if (!cinfo->constraints)
8292 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8293 MonoClass *cc = *candidate_class;
8295 if (mono_class_is_assignable_from (tc, cc))
8299 * This happens when we have the following:
8301 * Bar<K> where K : IFace
8302 * Foo<T, U> where T : U where U : IFace
8304 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8307 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8308 if (mono_gparam_is_assignable_from (target, cc))
8312 if (!*candidate_class)
8317 /*candidate itself must have a constraint that satisfy target*/
8318 if (cinfo->constraints) {
8319 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8320 MonoClass *cc = *candidate_class;
8321 if (mono_class_is_assignable_from (target, cc))
8329 * mono_class_is_assignable_from:
8330 * @klass: the class to be assigned to
8331 * @oklass: the source class
8333 * Returns: TRUE if an instance of object oklass can be assigned to an
8334 * instance of object @klass
8337 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8340 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8342 mono_class_init (klass);
8344 if (!oklass->inited)
8345 mono_class_init (oklass);
8347 if (mono_class_has_failure (klass) || mono_class_has_failure (oklass))
8350 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8351 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8353 return mono_gparam_is_assignable_from (klass, oklass);
8356 if (MONO_CLASS_IS_INTERFACE (klass)) {
8357 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8358 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8359 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8363 for (i = 0; constraints [i]; ++i) {
8364 if (mono_class_is_assignable_from (klass, constraints [i]))
8372 /* interface_offsets might not be set for dynamic classes */
8373 if (oklass->ref_info_handle && !oklass->interface_bitmap) {
8375 * oklass might be a generic type parameter but they have
8376 * interface_offsets set.
8378 gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8379 if (!is_ok (&error)) {
8380 mono_error_cleanup (&error);
8385 if (!oklass->interface_bitmap)
8386 /* Happens with generic instances of not-yet created dynamic types */
8388 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8391 if (mono_class_has_variant_generic_params (klass)) {
8393 mono_class_setup_interfaces (oklass, &error);
8394 if (!mono_error_ok (&error)) {
8395 mono_error_cleanup (&error);
8399 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8400 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8401 MonoClass *iface = oklass->interfaces_packed [i];
8403 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8408 } else if (klass->delegate) {
8409 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8411 }else if (klass->rank) {
8412 MonoClass *eclass, *eoclass;
8414 if (oklass->rank != klass->rank)
8417 /* vectors vs. one dimensional arrays */
8418 if (oklass->byval_arg.type != klass->byval_arg.type)
8421 eclass = klass->cast_class;
8422 eoclass = oklass->cast_class;
8425 * a is b does not imply a[] is b[] when a is a valuetype, and
8426 * b is a reference type.
8429 if (eoclass->valuetype) {
8430 if ((eclass == mono_defaults.enum_class) ||
8431 (eclass == mono_defaults.enum_class->parent) ||
8432 (eclass == mono_defaults.object_class))
8436 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8437 } else if (mono_class_is_nullable (klass)) {
8438 if (mono_class_is_nullable (oklass))
8439 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8441 return mono_class_is_assignable_from (klass->cast_class, oklass);
8442 } else if (klass == mono_defaults.object_class)
8445 return mono_class_has_parent (oklass, klass);
8448 /*Check if @oklass is variant compatible with @klass.*/
8450 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8453 MonoType **klass_argv, **oklass_argv;
8454 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8455 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8457 /*Viable candidates are instances of the same generic interface*/
8458 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8461 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8462 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8464 for (j = 0; j < container->type_argc; ++j) {
8465 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8466 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8468 if (param1_class->valuetype != param2_class->valuetype)
8472 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8473 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8475 if (param1_class != param2_class) {
8476 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8477 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8479 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8480 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8488 /*Check if @candidate implements the interface @target*/
8490 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8494 gboolean is_variant = mono_class_has_variant_generic_params (target);
8496 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8497 if (mono_class_is_variant_compatible_slow (target, candidate))
8502 if (candidate == target)
8505 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8506 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8507 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (candidate);
8509 if (tb && tb->interfaces) {
8510 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8511 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8512 MonoClass *iface_class;
8514 /* we can't realize the type here since it can do pretty much anything. */
8517 iface_class = mono_class_from_mono_type (iface->type);
8518 if (iface_class == target)
8520 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8522 if (mono_class_implement_interface_slow (target, iface_class))
8527 /*setup_interfaces don't mono_class_init anything*/
8528 /*FIXME this doesn't handle primitive type arrays.
8529 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8530 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8532 mono_class_setup_interfaces (candidate, &error);
8533 if (!mono_error_ok (&error)) {
8534 mono_error_cleanup (&error);
8538 for (i = 0; i < candidate->interface_count; ++i) {
8539 if (candidate->interfaces [i] == target)
8542 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8545 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8549 candidate = candidate->parent;
8550 } while (candidate);
8556 * Check if @oklass can be assigned to @klass.
8557 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8560 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8562 if (candidate == target)
8564 if (target == mono_defaults.object_class)
8567 if (mono_class_has_parent (candidate, target))
8570 /*If target is not an interface there is no need to check them.*/
8571 if (MONO_CLASS_IS_INTERFACE (target))
8572 return mono_class_implement_interface_slow (target, candidate);
8574 if (target->delegate && mono_class_has_variant_generic_params (target))
8575 return mono_class_is_variant_compatible (target, candidate, FALSE);
8578 MonoClass *eclass, *eoclass;
8580 if (target->rank != candidate->rank)
8583 /* vectors vs. one dimensional arrays */
8584 if (target->byval_arg.type != candidate->byval_arg.type)
8587 eclass = target->cast_class;
8588 eoclass = candidate->cast_class;
8591 * a is b does not imply a[] is b[] when a is a valuetype, and
8592 * b is a reference type.
8595 if (eoclass->valuetype) {
8596 if ((eclass == mono_defaults.enum_class) ||
8597 (eclass == mono_defaults.enum_class->parent) ||
8598 (eclass == mono_defaults.object_class))
8602 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8604 /*FIXME properly handle nullables */
8605 /*FIXME properly handle (M)VAR */
8610 * mono_class_get_cctor:
8611 * @klass: A MonoClass pointer
8613 * Returns: The static constructor of @klass if it exists, NULL otherwise.
8616 mono_class_get_cctor (MonoClass *klass)
8618 MonoCachedClassInfo cached_info;
8620 if (image_is_dynamic (klass->image)) {
8622 * has_cctor is not set for these classes because mono_class_init () is
8625 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8628 if (!klass->has_cctor)
8631 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8633 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8634 if (!mono_error_ok (&error))
8635 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8639 if (mono_class_is_ginst (klass) && !klass->methods)
8640 return mono_class_get_inflated_method (klass, mono_class_get_cctor (mono_class_get_generic_class (klass)->container_class));
8642 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8646 * mono_class_get_finalizer:
8647 * @klass: The MonoClass pointer
8649 * Returns: The finalizer method of @klass if it exists, NULL otherwise.
8652 mono_class_get_finalizer (MonoClass *klass)
8654 MonoCachedClassInfo cached_info;
8657 mono_class_init (klass);
8658 if (!mono_class_has_finalizer (klass))
8661 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8663 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8664 if (!mono_error_ok (&error))
8665 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8668 mono_class_setup_vtable (klass);
8669 return klass->vtable [finalize_slot];
8674 * mono_class_needs_cctor_run:
8675 * @klass: the MonoClass pointer
8676 * @caller: a MonoMethod describing the caller
8678 * Determines whenever the class has a static constructor and whenever it
8679 * needs to be called when executing CALLER.
8682 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8686 method = mono_class_get_cctor (klass);
8688 return (method == caller) ? FALSE : TRUE;
8694 * mono_class_array_element_size:
8697 * Returns: The number of bytes an element of type @klass
8698 * uses when stored into an array.
8701 mono_class_array_element_size (MonoClass *klass)
8703 MonoType *type = &klass->byval_arg;
8706 switch (type->type) {
8709 case MONO_TYPE_BOOLEAN:
8713 case MONO_TYPE_CHAR:
8722 case MONO_TYPE_CLASS:
8723 case MONO_TYPE_STRING:
8724 case MONO_TYPE_OBJECT:
8725 case MONO_TYPE_SZARRAY:
8726 case MONO_TYPE_ARRAY:
8727 return sizeof (gpointer);
8732 case MONO_TYPE_VALUETYPE:
8733 if (type->data.klass->enumtype) {
8734 type = mono_class_enum_basetype (type->data.klass);
8735 klass = klass->element_class;
8738 return mono_class_instance_size (klass) - sizeof (MonoObject);
8739 case MONO_TYPE_GENERICINST:
8740 type = &type->data.generic_class->container_class->byval_arg;
8743 case MONO_TYPE_MVAR: {
8746 return mono_type_size (type, &align);
8748 case MONO_TYPE_VOID:
8752 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8758 * mono_array_element_size:
8759 * @ac: pointer to a #MonoArrayClass
8761 * Returns: The size of single array element.
8764 mono_array_element_size (MonoClass *ac)
8766 g_assert (ac->rank);
8767 return ac->sizes.element_size;
8771 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8772 MonoGenericContext *context)
8775 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8776 g_assert (mono_error_ok (&error));
8781 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8782 MonoGenericContext *context, MonoError *error)
8784 mono_error_init (error);
8786 if (image_is_dynamic (image)) {
8787 MonoClass *tmp_handle_class;
8788 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
8790 mono_error_assert_ok (error);
8791 g_assert (tmp_handle_class);
8793 *handle_class = tmp_handle_class;
8795 if (tmp_handle_class == mono_defaults.typehandle_class)
8796 return &((MonoClass*)obj)->byval_arg;
8801 switch (token & 0xff000000) {
8802 case MONO_TOKEN_TYPE_DEF:
8803 case MONO_TOKEN_TYPE_REF:
8804 case MONO_TOKEN_TYPE_SPEC: {
8807 *handle_class = mono_defaults.typehandle_class;
8808 type = mono_type_get_checked (image, token, context, error);
8812 mono_class_init (mono_class_from_mono_type (type));
8813 /* We return a MonoType* as handle */
8816 case MONO_TOKEN_FIELD_DEF: {
8818 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8820 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8824 *handle_class = mono_defaults.fieldhandle_class;
8825 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8829 mono_class_init (klass);
8830 return mono_class_get_field (klass, token);
8832 case MONO_TOKEN_METHOD_DEF:
8833 case MONO_TOKEN_METHOD_SPEC: {
8835 meth = mono_get_method_checked (image, token, NULL, context, error);
8837 *handle_class = mono_defaults.methodhandle_class;
8843 case MONO_TOKEN_MEMBER_REF: {
8844 guint32 cols [MONO_MEMBERREF_SIZE];
8846 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8847 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8848 mono_metadata_decode_blob_size (sig, &sig);
8849 if (*sig == 0x6) { /* it's a field */
8851 MonoClassField *field;
8852 field = mono_field_from_token_checked (image, token, &klass, context, error);
8854 *handle_class = mono_defaults.fieldhandle_class;
8858 meth = mono_get_method_checked (image, token, NULL, context, error);
8860 *handle_class = mono_defaults.methodhandle_class;
8865 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8871 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
8873 MonoClass *handle_class;
8874 mono_error_init (error);
8875 return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
8879 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
8881 return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
8884 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8887 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8889 get_cached_class_info = func;
8893 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8895 if (!get_cached_class_info)
8898 return get_cached_class_info (klass, res);
8902 mono_install_get_class_from_name (MonoGetClassFromName func)
8904 get_class_from_name = func;
8908 * mono_class_get_image:
8910 * Use this method to get the `MonoImage*` where this class came from.
8912 * Returns: The image where this class is defined.
8915 mono_class_get_image (MonoClass *klass)
8917 return klass->image;
8921 * mono_class_get_element_class:
8922 * @klass: the MonoClass to act on
8924 * Use this function to get the element class of an array.
8926 * Returns: The element class of an array.
8929 mono_class_get_element_class (MonoClass *klass)
8931 return klass->element_class;
8935 * mono_class_is_valuetype:
8936 * @klass: the MonoClass to act on
8938 * Use this method to determine if the provided `MonoClass*` represents a value type,
8939 * or a reference type.
8941 * Returns: TRUE if the MonoClass represents a ValueType, FALSE if it represents a reference type.
8944 mono_class_is_valuetype (MonoClass *klass)
8946 return klass->valuetype;
8950 * mono_class_is_enum:
8951 * @klass: the MonoClass to act on
8953 * Use this function to determine if the provided `MonoClass*` represents an enumeration.
8955 * Returns: TRUE if the MonoClass represents an enumeration.
8958 mono_class_is_enum (MonoClass *klass)
8960 return klass->enumtype;
8964 * mono_class_enum_basetype:
8965 * @klass: the MonoClass to act on
8967 * Use this function to get the underlying type for an enumeration value.
8969 * Returns: The underlying type representation for an enumeration.
8972 mono_class_enum_basetype (MonoClass *klass)
8974 if (klass->element_class == klass)
8975 /* SRE or broken types */
8978 return &klass->element_class->byval_arg;
8982 * mono_class_get_parent
8983 * @klass: the MonoClass to act on
8985 * Returns: The parent class for this class.
8988 mono_class_get_parent (MonoClass *klass)
8990 return klass->parent;
8994 * mono_class_get_nesting_type:
8995 * @klass: the MonoClass to act on
8997 * Use this function to obtain the class that the provided `MonoClass*` is nested on.
8999 * If the return is NULL, this indicates that this class is not nested.
9001 * Returns: The container type where this type is nested or NULL if this type is not a nested type.
9004 mono_class_get_nesting_type (MonoClass *klass)
9006 return klass->nested_in;
9010 * mono_class_get_rank:
9011 * @klass: the MonoClass to act on
9013 * Returns: The rank for the array (the number of dimensions).
9016 mono_class_get_rank (MonoClass *klass)
9022 * mono_class_get_name
9023 * @klass: the MonoClass to act on
9025 * Returns: The name of the class.
9028 mono_class_get_name (MonoClass *klass)
9034 * mono_class_get_namespace:
9035 * @klass: the MonoClass to act on
9037 * Returns: The namespace of the class.
9040 mono_class_get_namespace (MonoClass *klass)
9042 return klass->name_space;
9046 * mono_class_get_type:
9047 * @klass: the MonoClass to act on
9049 * This method returns the internal Type representation for the class.
9051 * Returns: The MonoType from the class.
9054 mono_class_get_type (MonoClass *klass)
9056 return &klass->byval_arg;
9060 * mono_class_get_type_token:
9061 * @klass: the MonoClass to act on
9063 * This method returns type token for the class.
9065 * Returns: The type token for the class.
9068 mono_class_get_type_token (MonoClass *klass)
9070 return klass->type_token;
9074 * mono_class_get_byref_type:
9075 * @klass: the MonoClass to act on
9080 mono_class_get_byref_type (MonoClass *klass)
9082 return &klass->this_arg;
9086 * mono_class_num_fields:
9087 * @klass: the MonoClass to act on
9089 * Returns: The number of static and instance fields in the class.
9092 mono_class_num_fields (MonoClass *klass)
9094 return mono_class_get_field_count (klass);
9098 * mono_class_num_methods:
9099 * @klass: the MonoClass to act on
9101 * Returns: The number of methods in the class.
9104 mono_class_num_methods (MonoClass *klass)
9106 return mono_class_get_method_count (klass);
9110 * mono_class_num_properties
9111 * @klass: the MonoClass to act on
9113 * Returns: The number of properties in the class.
9116 mono_class_num_properties (MonoClass *klass)
9118 mono_class_setup_properties (klass);
9120 return klass->ext->property.count;
9124 * mono_class_num_events:
9125 * @klass: the MonoClass to act on
9127 * Returns: The number of events in the class.
9130 mono_class_num_events (MonoClass *klass)
9132 mono_class_setup_events (klass);
9134 return klass->ext->event.count;
9138 * mono_class_get_fields:
9139 * @klass: the MonoClass to act on
9141 * This routine is an iterator routine for retrieving the fields in a class.
9143 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9144 * iterate over all of the elements. When no more values are
9145 * available, the return value is NULL.
9147 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
9150 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9152 MonoClassField* field;
9156 mono_class_setup_fields (klass);
9157 if (mono_class_has_failure (klass))
9159 /* start from the first */
9160 if (mono_class_get_field_count (klass)) {
9161 *iter = &klass->fields [0];
9162 return &klass->fields [0];
9168 field = (MonoClassField *)*iter;
9170 if (field < &klass->fields [mono_class_get_field_count (klass)]) {
9178 * mono_class_get_methods
9179 * @klass: the MonoClass to act on
9181 * This routine is an iterator routine for retrieving the fields in a class.
9183 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9184 * iterate over all of the elements. When no more values are
9185 * available, the return value is NULL.
9187 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
9190 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9192 MonoMethod** method;
9196 mono_class_setup_methods (klass);
9199 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9200 * FIXME we should better report this error to the caller
9202 if (!klass->methods)
9204 /* start from the first */
9205 if (mono_class_get_method_count (klass)) {
9206 *iter = &klass->methods [0];
9207 return klass->methods [0];
9213 method = (MonoMethod **)*iter;
9215 if (method < &klass->methods [mono_class_get_method_count (klass)]) {
9223 * mono_class_get_virtual_methods:
9225 * Iterate over the virtual methods of KLASS.
9227 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9230 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9232 MonoMethod** method;
9235 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9237 mono_class_setup_methods (klass);
9239 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9240 * FIXME we should better report this error to the caller
9242 if (!klass->methods)
9244 /* start from the first */
9245 method = &klass->methods [0];
9247 method = (MonoMethod **)*iter;
9250 int mcount = mono_class_get_method_count (klass);
9251 while (method < &klass->methods [mcount]) {
9252 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9256 if (method < &klass->methods [mcount]) {
9263 /* Search directly in metadata to avoid calling setup_methods () */
9264 MonoMethod *res = NULL;
9270 start_index = GPOINTER_TO_UINT (*iter);
9273 int first_idx = mono_class_get_first_method_idx (klass);
9274 int mcount = mono_class_get_method_count (klass);
9275 for (i = start_index; i < mcount; ++i) {
9278 /* first_idx points into the methodptr table */
9279 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
9281 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9287 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9288 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9290 /* Add 1 here so the if (*iter) check fails */
9291 *iter = GUINT_TO_POINTER (i + 1);
9300 * mono_class_get_properties:
9301 * @klass: the MonoClass to act on
9303 * This routine is an iterator routine for retrieving the properties in a class.
9305 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9306 * iterate over all of the elements. When no more values are
9307 * available, the return value is NULL.
9309 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9312 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9314 MonoProperty* property;
9318 mono_class_setup_properties (klass);
9319 /* start from the first */
9320 if (klass->ext->property.count) {
9321 *iter = &klass->ext->properties [0];
9322 return (MonoProperty *)*iter;
9328 property = (MonoProperty *)*iter;
9330 if (property < &klass->ext->properties [klass->ext->property.count]) {
9332 return (MonoProperty *)*iter;
9338 * mono_class_get_events:
9339 * @klass: the MonoClass to act on
9341 * This routine is an iterator routine for retrieving the properties in a class.
9343 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9344 * iterate over all of the elements. When no more values are
9345 * available, the return value is NULL.
9347 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9350 mono_class_get_events (MonoClass* klass, gpointer *iter)
9356 mono_class_setup_events (klass);
9357 /* start from the first */
9358 if (klass->ext->event.count) {
9359 *iter = &klass->ext->events [0];
9360 return (MonoEvent *)*iter;
9366 event = (MonoEvent *)*iter;
9368 if (event < &klass->ext->events [klass->ext->event.count]) {
9370 return (MonoEvent *)*iter;
9376 * mono_class_get_interfaces
9377 * @klass: the MonoClass to act on
9379 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9381 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9382 * iterate over all of the elements. When no more values are
9383 * available, the return value is NULL.
9385 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9388 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9396 mono_class_init (klass);
9397 if (!klass->interfaces_inited) {
9398 mono_class_setup_interfaces (klass, &error);
9399 if (!mono_error_ok (&error)) {
9400 mono_error_cleanup (&error);
9404 /* start from the first */
9405 if (klass->interface_count) {
9406 *iter = &klass->interfaces [0];
9407 return klass->interfaces [0];
9413 iface = (MonoClass **)*iter;
9415 if (iface < &klass->interfaces [klass->interface_count]) {
9423 setup_nested_types (MonoClass *klass)
9426 GList *classes, *nested_classes, *l;
9429 if (klass->nested_classes_inited)
9432 if (!klass->type_token)
9433 klass->nested_classes_inited = TRUE;
9435 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9439 guint32 cols [MONO_NESTED_CLASS_SIZE];
9440 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9441 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9442 if (!mono_error_ok (&error)) {
9443 /*FIXME don't swallow the error message*/
9444 mono_error_cleanup (&error);
9446 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9450 classes = g_list_prepend (classes, nclass);
9452 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9455 mono_class_alloc_ext (klass);
9457 nested_classes = NULL;
9458 for (l = classes; l; l = l->next)
9459 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9460 g_list_free (classes);
9462 mono_image_lock (klass->image);
9464 mono_memory_barrier ();
9465 if (!klass->nested_classes_inited) {
9466 klass->ext->nested_classes = nested_classes;
9467 mono_memory_barrier ();
9468 klass->nested_classes_inited = TRUE;
9471 mono_image_unlock (klass->image);
9475 * mono_class_get_nested_types
9476 * @klass: the MonoClass to act on
9478 * This routine is an iterator routine for retrieving the nested types of a class.
9479 * This works only if @klass is non-generic, or a generic type definition.
9481 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9482 * iterate over all of the elements. When no more values are
9483 * available, the return value is NULL.
9485 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9488 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9494 if (!klass->nested_classes_inited)
9495 setup_nested_types (klass);
9498 /* start from the first */
9499 if (klass->ext && klass->ext->nested_classes) {
9500 *iter = klass->ext->nested_classes;
9501 return (MonoClass *)klass->ext->nested_classes->data;
9503 /* no nested types */
9507 item = (GList *)*iter;
9511 return (MonoClass *)item->data;
9518 * mono_class_is_delegate
9519 * @klass: the MonoClass to act on
9521 * Returns: TRUE if the MonoClass represents a System.Delegate.
9524 mono_class_is_delegate (MonoClass *klass)
9526 return klass->delegate;
9530 * mono_class_implements_interface
9531 * @klass: The MonoClass to act on
9532 * @interface: The interface to check if @klass implements.
9534 * Returns: TRUE if @klass implements @interface.
9537 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9539 return mono_class_is_assignable_from (iface, klass);
9543 * mono_field_get_name:
9544 * @field: the MonoClassField to act on
9546 * Returns: The name of the field.
9549 mono_field_get_name (MonoClassField *field)
9555 * mono_field_get_type:
9556 * @field: the MonoClassField to act on
9558 * Returns: MonoType of the field.
9561 mono_field_get_type (MonoClassField *field)
9564 MonoType *type = mono_field_get_type_checked (field, &error);
9565 if (!mono_error_ok (&error)) {
9566 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9567 mono_error_cleanup (&error);
9574 * mono_field_get_type_checked:
9575 * @field: the MonoClassField to act on
9576 * @error: used to return any erro found while retrieving @field type
9578 * Returns: MonoType of the field.
9581 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9583 mono_error_init (error);
9585 mono_field_resolve_type (field, error);
9590 * mono_field_get_parent:
9591 * @field: the MonoClassField to act on
9593 * Returns: MonoClass where the field was defined.
9596 mono_field_get_parent (MonoClassField *field)
9598 return field->parent;
9602 * mono_field_get_flags;
9603 * @field: the MonoClassField to act on
9605 * The metadata flags for a field are encoded using the
9606 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9608 * Returns: The flags for the field.
9611 mono_field_get_flags (MonoClassField *field)
9614 return mono_field_resolve_flags (field);
9615 return field->type->attrs;
9619 * mono_field_get_offset:
9620 * @field: the MonoClassField to act on
9622 * Returns: The field offset.
9625 mono_field_get_offset (MonoClassField *field)
9627 return field->offset;
9631 mono_field_get_rva (MonoClassField *field)
9635 MonoClass *klass = field->parent;
9636 MonoFieldDefaultValue *field_def_values;
9638 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9640 if (!klass->ext || !klass->ext->field_def_values) {
9641 mono_class_alloc_ext (klass);
9643 field_def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
9645 mono_image_lock (klass->image);
9646 if (!klass->ext->field_def_values)
9647 klass->ext->field_def_values = field_def_values;
9648 mono_image_unlock (klass->image);
9651 field_index = mono_field_get_index (field);
9653 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9654 int first_field_idx = mono_class_get_first_field_idx (klass);
9655 mono_metadata_field_info (field->parent->image, first_field_idx + field_index, NULL, &rva, NULL);
9657 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9658 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9661 return klass->ext->field_def_values [field_index].data;
9665 * mono_field_get_data:
9666 * @field: the MonoClassField to act on
9668 * Returns: A pointer to the metadata constant value or to the field
9669 * data if it has an RVA flag.
9672 mono_field_get_data (MonoClassField *field)
9674 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9675 MonoTypeEnum def_type;
9677 return mono_class_get_field_default_value (field, &def_type);
9678 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9679 return mono_field_get_rva (field);
9686 * mono_property_get_name:
9687 * @prop: the MonoProperty to act on
9689 * Returns: The name of the property
9692 mono_property_get_name (MonoProperty *prop)
9698 * mono_property_get_set_method
9699 * @prop: the MonoProperty to act on.
9701 * Returns: The setter method of the property (A MonoMethod)
9704 mono_property_get_set_method (MonoProperty *prop)
9710 * mono_property_get_get_method
9711 * @prop: the MonoProperty to act on.
9713 * Returns: The setter method of the property (A MonoMethod)
9716 mono_property_get_get_method (MonoProperty *prop)
9722 * mono_property_get_parent:
9723 * @prop: the MonoProperty to act on.
9725 * Returns: The MonoClass where the property was defined.
9728 mono_property_get_parent (MonoProperty *prop)
9730 return prop->parent;
9734 * mono_property_get_flags:
9735 * @prop: the MonoProperty to act on.
9737 * The metadata flags for a property are encoded using the
9738 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9740 * Returns: The flags for the property.
9743 mono_property_get_flags (MonoProperty *prop)
9749 * mono_event_get_name:
9750 * @event: the MonoEvent to act on
9752 * Returns: The name of the event.
9755 mono_event_get_name (MonoEvent *event)
9761 * mono_event_get_add_method:
9762 * @event: The MonoEvent to act on.
9764 * Returns: The @add' method for the event (a MonoMethod).
9767 mono_event_get_add_method (MonoEvent *event)
9773 * mono_event_get_remove_method:
9774 * @event: The MonoEvent to act on.
9776 * Returns: The @remove method for the event (a MonoMethod).
9779 mono_event_get_remove_method (MonoEvent *event)
9781 return event->remove;
9785 * mono_event_get_raise_method:
9786 * @event: The MonoEvent to act on.
9788 * Returns: The @raise method for the event (a MonoMethod).
9791 mono_event_get_raise_method (MonoEvent *event)
9793 return event->raise;
9797 * mono_event_get_parent:
9798 * @event: the MonoEvent to act on.
9800 * Returns: The MonoClass where the event is defined.
9803 mono_event_get_parent (MonoEvent *event)
9805 return event->parent;
9809 * mono_event_get_flags
9810 * @event: the MonoEvent to act on.
9812 * The metadata flags for an event are encoded using the
9813 * EVENT_* constants. See the tabledefs.h file for details.
9815 * Returns: The flags for the event.
9818 mono_event_get_flags (MonoEvent *event)
9820 return event->attrs;
9824 * mono_class_get_method_from_name:
9825 * @klass: where to look for the method
9826 * @name: name of the method
9827 * @param_count: number of parameters. -1 for any number.
9829 * Obtains a MonoMethod with a given name and number of parameters.
9830 * It only works if there are no multiple signatures for any given method name.
9833 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9835 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9839 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9841 MonoMethod *res = NULL;
9844 /* Search directly in the metadata to avoid calling setup_methods () */
9845 int first_idx = mono_class_get_first_method_idx (klass);
9846 int mcount = mono_class_get_method_count (klass);
9847 for (i = 0; i < mcount; ++i) {
9849 guint32 cols [MONO_METHOD_SIZE];
9851 MonoMethodSignature *sig;
9853 /* first_idx points into the methodptr table */
9854 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, first_idx + i, cols, MONO_METHOD_SIZE);
9856 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9857 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9859 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9862 if (param_count == -1) {
9866 sig = mono_method_signature_checked (method, &error);
9868 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9871 if (sig->param_count == param_count) {
9882 * mono_class_get_method_from_name_flags:
9883 * @klass: where to look for the method
9884 * @name_space: name of the method
9885 * @param_count: number of parameters. -1 for any number.
9886 * @flags: flags which must be set in the method
9888 * Obtains a MonoMethod with a given name and number of parameters.
9889 * It only works if there are no multiple signatures for any given method name.
9892 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9894 MonoMethod *res = NULL;
9897 mono_class_init (klass);
9899 if (mono_class_is_ginst (klass) && !klass->methods) {
9900 res = mono_class_get_method_from_name_flags (mono_class_get_generic_class (klass)->container_class, name, param_count, flags);
9903 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9904 if (!mono_error_ok (&error))
9905 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9910 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9911 mono_class_setup_methods (klass);
9913 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9914 See mono/tests/array_load_exception.il
9915 FIXME we should better report this error to the caller
9917 if (!klass->methods)
9919 int mcount = mono_class_get_method_count (klass);
9920 for (i = 0; i < mcount; ++i) {
9921 MonoMethod *method = klass->methods [i];
9923 if (method->name[0] == name [0] &&
9924 !strcmp (name, method->name) &&
9925 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9926 ((method->flags & flags) == flags)) {
9933 res = find_method_in_metadata (klass, name, param_count, flags);
9940 * mono_class_set_failure:
9941 * @klass: class in which the failure was detected
9942 * @ex_type: the kind of exception/error to be thrown (later)
9943 * @ex_data: exception data (specific to each type of exception/error)
9945 * Keep a detected failure informations in the class for later processing.
9946 * Note that only the first failure is kept.
9948 * LOCKING: Acquires the loader lock.
9951 mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error)
9953 g_assert (boxed_error != NULL);
9955 if (mono_class_has_failure (klass))
9958 mono_loader_lock ();
9959 klass->has_failure = 1;
9960 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, boxed_error);
9961 mono_loader_unlock ();
9967 mono_class_has_failure (const MonoClass *klass)
9969 g_assert (klass != NULL);
9970 return klass->has_failure != 0;
9975 * mono_class_set_type_load_failure:
9976 * @klass: class in which the failure was detected
9977 * @fmt: Printf-style error message string.
9979 * Collect detected failure informaion in the class for later processing.
9980 * The error is stored as a MonoErrorBoxed as with mono_error_set_type_load_class ()
9981 * Note that only the first failure is kept.
9983 * Returns FALSE if a failure was already set on the class, or TRUE otherwise.
9985 * LOCKING: Acquires the loader lock.
9988 mono_class_set_type_load_failure (MonoClass *klass, const char * fmt, ...)
9990 MonoError prepare_error;
9993 if (mono_class_has_failure (klass))
9996 mono_error_init (&prepare_error);
9998 va_start (args, fmt);
9999 mono_error_vset_type_load_class (&prepare_error, klass, fmt, args);
10002 MonoErrorBoxed *box = mono_error_box (&prepare_error, klass->image);
10003 mono_error_cleanup (&prepare_error);
10004 return mono_class_set_failure (klass, box);
10008 * mono_class_get_exception_data:
10010 * Return the exception_data property of KLASS.
10012 * LOCKING: Acquires the loader lock.
10015 mono_class_get_exception_data (const MonoClass *klass)
10017 return mono_image_property_lookup (klass->image, (MonoClass*)klass, MONO_CLASS_PROP_EXCEPTION_DATA);
10021 * mono_classes_init:
10023 * Initialize the resources used by this module.
10026 mono_classes_init (void)
10028 mono_os_mutex_init (&classes_mutex);
10030 mono_native_tls_alloc (&setup_fields_tls_id, NULL);
10031 mono_native_tls_alloc (&init_pending_tls_id, NULL);
10033 mono_counters_register ("MonoClassDef count",
10034 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_def_count);
10035 mono_counters_register ("MonoClassGtd count",
10036 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gtd_count);
10037 mono_counters_register ("MonoClassGenericInst count",
10038 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ginst_count);
10039 mono_counters_register ("MonoClassGenericParam count",
10040 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gparam_count);
10041 mono_counters_register ("MonoClassArray count",
10042 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_array_count);
10043 mono_counters_register ("MonoClassPointer count",
10044 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_pointer_count);
10045 mono_counters_register ("Inflated methods size",
10046 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
10047 mono_counters_register ("Inflated classes size",
10048 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
10049 mono_counters_register ("MonoClass size",
10050 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
10051 mono_counters_register ("MonoClassExt size",
10052 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
10054 mono_counters_register ("MonoClassExt count",
10055 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_count);
10059 * mono_classes_cleanup:
10061 * Free the resources used by this module.
10064 mono_classes_cleanup (void)
10066 mono_native_tls_free (setup_fields_tls_id);
10067 mono_native_tls_free (init_pending_tls_id);
10069 if (global_interface_bitset)
10070 mono_bitset_free (global_interface_bitset);
10071 global_interface_bitset = NULL;
10072 mono_os_mutex_destroy (&classes_mutex);
10076 * mono_class_get_exception_for_failure:
10077 * @klass: class in which the failure was detected
10079 * Return a constructed MonoException than the caller can then throw
10080 * using mono_raise_exception - or NULL if no failure is present (or
10081 * doesn't result in an exception).
10084 mono_class_get_exception_for_failure (MonoClass *klass)
10086 if (!mono_class_has_failure (klass))
10088 MonoError unboxed_error;
10089 mono_error_init (&unboxed_error);
10090 mono_error_set_for_class_failure (&unboxed_error, klass);
10091 return mono_error_convert_to_exception (&unboxed_error);
10095 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
10097 outer_klass = mono_class_get_generic_type_definition (outer_klass);
10098 inner_klass = mono_class_get_generic_type_definition (inner_klass);
10100 if (outer_klass == inner_klass)
10102 inner_klass = inner_klass->nested_in;
10103 } while (inner_klass);
10108 mono_class_get_generic_type_definition (MonoClass *klass)
10110 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
10111 return gklass ? gklass->container_class : klass;
10115 * Check if @klass is a subtype of @parent ignoring generic instantiations.
10117 * Generic instantiations are ignored for all super types of @klass.
10119 * Visibility checks ignoring generic instantiations.
10122 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
10125 klass = mono_class_get_generic_type_definition (klass);
10126 parent = mono_class_get_generic_type_definition (parent);
10127 mono_class_setup_supertypes (klass);
10129 for (i = 0; i < klass->idepth; ++i) {
10130 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
10136 * Subtype can only access parent members with family protection if the site object
10137 * is subclass of Subtype. For example:
10138 * class A { protected int x; }
10140 * void valid_access () {
10144 * void invalid_access () {
10151 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
10153 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
10156 if (context_klass == NULL)
10158 /*if access_klass is not member_klass context_klass must be type compat*/
10159 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10165 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10168 if (accessing == accessed)
10170 if (!accessed || !accessing)
10173 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10174 * anywhere so untrusted friends are not safe to access platform's code internals */
10175 if (mono_security_core_clr_enabled ()) {
10176 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10180 mono_assembly_load_friends (accessed);
10181 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10182 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10183 /* Be conservative with checks */
10184 if (!friend_->name)
10186 if (strcmp (accessing->aname.name, friend_->name))
10188 if (friend_->public_key_token [0]) {
10189 if (!accessing->aname.public_key_token [0])
10191 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10200 * If klass is a generic type or if it is derived from a generic type, return the
10201 * MonoClass of the generic definition
10202 * Returns NULL if not found
10205 get_generic_definition_class (MonoClass *klass)
10208 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
10209 if (gklass && gklass->container_class)
10210 return gklass->container_class;
10211 klass = klass->parent;
10217 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10220 for (i = 0; i < ginst->type_argc; ++i) {
10221 MonoType *type = ginst->type_argv[i];
10222 switch (type->type) {
10223 case MONO_TYPE_SZARRAY:
10224 if (!can_access_type (access_klass, type->data.klass))
10227 case MONO_TYPE_ARRAY:
10228 if (!can_access_type (access_klass, type->data.array->eklass))
10231 case MONO_TYPE_PTR:
10232 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10235 case MONO_TYPE_CLASS:
10236 case MONO_TYPE_VALUETYPE:
10237 case MONO_TYPE_GENERICINST:
10238 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10248 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10252 if (access_klass == member_klass)
10255 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10258 if (access_klass->element_class && !access_klass->enumtype)
10259 access_klass = access_klass->element_class;
10261 if (member_klass->element_class && !member_klass->enumtype)
10262 member_klass = member_klass->element_class;
10264 access_level = mono_class_get_flags (member_klass) & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10266 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10269 if (mono_class_is_ginst (member_klass) && !can_access_instantiation (access_klass, mono_class_get_generic_class (member_klass)->context.class_inst))
10272 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10275 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10278 /*Non nested type with nested visibility. We just fail it.*/
10279 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10282 switch (access_level) {
10283 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10284 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10286 case TYPE_ATTRIBUTE_PUBLIC:
10289 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10292 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10293 return is_nesting_type (member_klass, access_klass);
10295 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10296 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10298 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10299 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10301 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10302 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10303 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10305 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10306 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10307 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10312 /* FIXME: check visibility of type, too */
10314 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10316 MonoClass *member_generic_def;
10317 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10320 MonoGenericClass *access_gklass = mono_class_try_get_generic_class (access_klass);
10321 if (((access_gklass && access_gklass->container_class) ||
10322 mono_class_is_gtd (access_klass)) &&
10323 (member_generic_def = get_generic_definition_class (member_klass))) {
10324 MonoClass *access_container;
10326 if (mono_class_is_gtd (access_klass))
10327 access_container = access_klass;
10329 access_container = access_gklass->container_class;
10331 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10335 /* Partition I 8.5.3.2 */
10336 /* the access level values are the same for fields and methods */
10337 switch (access_level) {
10338 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10339 /* same compilation unit */
10340 return access_klass->image == member_klass->image;
10341 case FIELD_ATTRIBUTE_PRIVATE:
10342 return access_klass == member_klass;
10343 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10344 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10345 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10348 case FIELD_ATTRIBUTE_ASSEMBLY:
10349 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10350 case FIELD_ATTRIBUTE_FAMILY:
10351 if (is_valid_family_access (access_klass, member_klass, context_klass))
10354 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10355 if (is_valid_family_access (access_klass, member_klass, context_klass))
10357 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10358 case FIELD_ATTRIBUTE_PUBLIC:
10365 * mono_method_can_access_field:
10366 * @method: Method that will attempt to access the field
10367 * @field: the field to access
10369 * Used to determine if a method is allowed to access the specified field.
10371 * Returns: TRUE if the given @method is allowed to access the @field while following
10372 * the accessibility rules of the CLI.
10375 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10377 /* FIXME: check all overlapping fields */
10378 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10380 MonoClass *nested = method->klass->nested_in;
10382 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10385 nested = nested->nested_in;
10392 * mono_method_can_access_method:
10393 * @method: Method that will attempt to access the other method
10394 * @called: the method that we want to probe for accessibility.
10396 * Used to determine if the @method is allowed to access the specified @called method.
10398 * Returns: TRUE if the given @method is allowed to invoke the @called while following
10399 * the accessibility rules of the CLI.
10402 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10404 method = mono_method_get_method_definition (method);
10405 called = mono_method_get_method_definition (called);
10406 return mono_method_can_access_method_full (method, called, NULL);
10410 * mono_method_can_access_method_full:
10411 * @method: The caller method
10412 * @called: The called method
10413 * @context_klass: The static type on stack of the owner @called object used
10415 * This function must be used with instance calls, as they have more strict family accessibility.
10416 * It can be used with static methods, but context_klass should be NULL.
10418 * Returns: TRUE if caller have proper visibility and acessibility to @called
10421 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10423 /* Wrappers are except from access checks */
10424 if (method->wrapper_type != MONO_WRAPPER_NONE || called->wrapper_type != MONO_WRAPPER_NONE)
10427 MonoClass *access_class = method->klass;
10428 MonoClass *member_class = called->klass;
10429 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10431 MonoClass *nested = access_class->nested_in;
10433 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10436 nested = nested->nested_in;
10443 can = can_access_type (access_class, member_class);
10445 MonoClass *nested = access_class->nested_in;
10447 can = can_access_type (nested, member_class);
10450 nested = nested->nested_in;
10457 if (called->is_inflated) {
10458 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10459 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10468 * mono_method_can_access_field_full:
10469 * @method: The caller method
10470 * @field: The accessed field
10471 * @context_klass: The static type on stack of the owner @field object used
10473 * This function must be used with instance fields, as they have more strict family accessibility.
10474 * It can be used with static fields, but context_klass should be NULL.
10476 * Returns: TRUE if caller have proper visibility and acessibility to @field
10479 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10481 MonoClass *access_class = method->klass;
10482 MonoClass *member_class = field->parent;
10483 /* FIXME: check all overlapping fields */
10484 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10486 MonoClass *nested = access_class->nested_in;
10488 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10491 nested = nested->nested_in;
10498 can = can_access_type (access_class, member_class);
10500 MonoClass *nested = access_class->nested_in;
10502 can = can_access_type (nested, member_class);
10505 nested = nested->nested_in;
10515 * mono_class_can_access_class:
10516 * @source_class: The source class
10517 * @target_class: The accessed class
10519 * This function returns is @target_class is visible to @source_class
10521 * Returns: TRUE if source have proper visibility and acessibility to target
10524 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10526 return can_access_type (source_class, target_class);
10530 * mono_type_is_valid_enum_basetype:
10531 * @type: The MonoType to check
10533 * Returns: TRUE if the type can be used as the basetype of an enum
10535 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10536 switch (type->type) {
10539 case MONO_TYPE_BOOLEAN:
10542 case MONO_TYPE_CHAR:
10556 * mono_class_is_valid_enum:
10557 * @klass: An enum class to be validated
10559 * This method verify the required properties an enum should have.
10561 * Returns: TRUE if the informed enum class is valid
10563 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10564 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10565 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10568 mono_class_is_valid_enum (MonoClass *klass)
10570 MonoClassField * field;
10571 gpointer iter = NULL;
10572 gboolean found_base_field = FALSE;
10574 g_assert (klass->enumtype);
10575 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10576 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10580 if (!mono_class_is_auto_layout (klass))
10583 while ((field = mono_class_get_fields (klass, &iter))) {
10584 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10585 if (found_base_field)
10587 found_base_field = TRUE;
10588 if (!mono_type_is_valid_enum_basetype (field->type))
10593 if (!found_base_field)
10596 if (mono_class_get_method_count (klass) > 0)
10603 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10605 return gklass->context.class_inst == mono_class_get_generic_container (gklass->container_class)->context.class_inst;
10609 * mono_class_setup_interface_id:
10611 * Initializes MonoClass::interface_id if required.
10613 * LOCKING: Acquires the loader lock.
10616 mono_class_setup_interface_id (MonoClass *klass)
10618 mono_loader_lock ();
10619 if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10620 klass->interface_id = mono_get_unique_iid (klass);
10621 mono_loader_unlock ();
10625 * mono_class_alloc_ext:
10627 * Allocate klass->ext if not already done.
10630 mono_class_alloc_ext (MonoClass *klass)
10637 ext = (MonoClassExt *)mono_class_alloc0 (klass, sizeof (MonoClassExt));
10638 mono_image_lock (klass->image);
10639 mono_memory_barrier ();
10642 class_ext_size += sizeof (MonoClassExt);
10644 mono_image_unlock (klass->image);
10648 * mono_class_setup_interfaces:
10650 * Initialize klass->interfaces/interfaces_count.
10651 * LOCKING: Acquires the loader lock.
10652 * This function can fail the type.
10655 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10657 int i, interface_count;
10658 MonoClass **interfaces;
10660 mono_error_init (error);
10662 if (klass->interfaces_inited)
10665 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10666 MonoType *args [1];
10668 /* generic IList, ICollection, IEnumerable */
10669 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10670 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10672 args [0] = &klass->element_class->byval_arg;
10673 interfaces [0] = mono_class_bind_generic_parameters (
10674 mono_defaults.generic_ilist_class, 1, args, FALSE);
10675 if (interface_count > 1)
10676 interfaces [1] = mono_class_bind_generic_parameters (
10677 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10678 } else if (mono_class_is_ginst (klass)) {
10679 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
10681 mono_class_setup_interfaces (gklass, error);
10682 if (!mono_error_ok (error)) {
10683 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10687 interface_count = gklass->interface_count;
10688 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10689 for (i = 0; i < interface_count; i++) {
10690 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (mono_class_get_generic_class (klass)), error);
10691 if (!mono_error_ok (error)) {
10692 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10697 interface_count = 0;
10701 mono_image_lock (klass->image);
10703 if (!klass->interfaces_inited) {
10704 klass->interface_count = interface_count;
10705 klass->interfaces = interfaces;
10707 mono_memory_barrier ();
10709 klass->interfaces_inited = TRUE;
10712 mono_image_unlock (klass->image);
10716 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10718 MonoClass *klass = field->parent;
10719 MonoImage *image = klass->image;
10720 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10722 int field_idx = field - klass->fields;
10724 mono_error_init (error);
10727 MonoClassField *gfield = >d->fields [field_idx];
10728 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10729 if (!mono_error_ok (error)) {
10730 char *full_name = mono_type_get_full_name (gtd);
10731 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));
10732 g_free (full_name);
10735 ftype = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10736 if (!mono_error_ok (error)) {
10737 char *full_name = mono_type_get_full_name (klass);
10738 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));
10739 g_free (full_name);
10743 guint32 cols [MONO_FIELD_SIZE];
10744 MonoGenericContainer *container = NULL;
10745 int idx = mono_class_get_first_field_idx (klass) + field_idx;
10747 /*FIXME, in theory we do not lazy load SRE fields*/
10748 g_assert (!image_is_dynamic (image));
10750 if (mono_class_is_gtd (klass)) {
10751 container = mono_class_get_generic_container (klass);
10753 container = mono_class_get_generic_container (gtd);
10754 g_assert (container);
10757 /* first_field_idx and idx points into the fieldptr table */
10758 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10760 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10761 char *full_name = mono_type_get_full_name (klass);
10762 mono_error_set_type_load_class (error, klass, "Could not verify field '%s:%s' signature", full_name, field->name);;
10763 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
10764 g_free (full_name);
10768 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10770 mono_metadata_decode_value (sig, &sig);
10771 /* FIELD signature == 0x06 */
10772 g_assert (*sig == 0x06);
10774 ftype = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10776 char *full_name = mono_type_get_full_name (klass);
10777 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));
10778 g_free (full_name);
10781 mono_memory_barrier ();
10782 field->type = ftype;
10786 mono_field_resolve_flags (MonoClassField *field)
10788 MonoClass *klass = field->parent;
10789 MonoImage *image = klass->image;
10790 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10791 int field_idx = field - klass->fields;
10795 MonoClassField *gfield = >d->fields [field_idx];
10796 return mono_field_get_flags (gfield);
10798 int idx = mono_class_get_first_field_idx (klass) + field_idx;
10800 /*FIXME, in theory we do not lazy load SRE fields*/
10801 g_assert (!image_is_dynamic (image));
10803 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10808 * mono_class_get_fields_lazy:
10809 * @klass: the MonoClass to act on
10811 * This routine is an iterator routine for retrieving the fields in a class.
10812 * Only minimal information about fields are loaded. Accessors must be used
10813 * for all MonoClassField returned.
10815 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10816 * iterate over all of the elements. When no more values are
10817 * available, the return value is NULL.
10819 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10822 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10824 MonoClassField* field;
10828 mono_class_setup_basic_field_info (klass);
10829 if (!klass->fields)
10831 /* start from the first */
10832 if (mono_class_get_field_count (klass)) {
10833 *iter = &klass->fields [0];
10834 return (MonoClassField *)*iter;
10840 field = (MonoClassField *)*iter;
10842 if (field < &klass->fields [mono_class_get_field_count (klass)]) {
10844 return (MonoClassField *)*iter;
10850 mono_class_full_name (MonoClass *klass)
10852 return mono_type_full_name (&klass->byval_arg);
10855 /* Declare all shared lazy type lookup functions */
10856 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, System.Runtime.InteropServices, SafeHandle)