2 * class.c: Class management for the Mono runtime
5 * Miguel de Icaza (miguel@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9 * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
10 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
20 #include <mono/metadata/image.h>
21 #include <mono/metadata/image-internals.h>
22 #include <mono/metadata/assembly.h>
23 #include <mono/metadata/assembly-internals.h>
24 #include <mono/metadata/metadata.h>
25 #include <mono/metadata/metadata-internals.h>
26 #include <mono/metadata/profiler-private.h>
27 #include <mono/metadata/tabledefs.h>
28 #include <mono/metadata/tokentype.h>
29 #include <mono/metadata/class-internals.h>
30 #include <mono/metadata/object.h>
31 #include <mono/metadata/appdomain.h>
32 #include <mono/metadata/mono-endian.h>
33 #include <mono/metadata/debug-helpers.h>
34 #include <mono/metadata/reflection.h>
35 #include <mono/metadata/exception.h>
36 #include <mono/metadata/security-manager.h>
37 #include <mono/metadata/security-core-clr.h>
38 #include <mono/metadata/attrdefs.h>
39 #include <mono/metadata/gc-internals.h>
40 #include <mono/metadata/verify-internals.h>
41 #include <mono/metadata/mono-debug.h>
42 #include <mono/utils/mono-counters.h>
43 #include <mono/utils/mono-string.h>
44 #include <mono/utils/mono-error-internals.h>
45 #include <mono/utils/mono-logger-internals.h>
46 #include <mono/utils/mono-memory-model.h>
47 #include <mono/utils/atomic.h>
48 #include <mono/utils/bsearch.h>
49 #include <mono/utils/checked-build.h>
53 gboolean mono_print_vtable = FALSE;
54 gboolean mono_align_small_structs = FALSE;
57 guint32 inflated_classes_size, inflated_methods_size;
58 guint32 classes_size, class_ext_size, class_ext_count;
59 guint32 class_def_count, class_gtd_count, class_ginst_count, class_gparam_count, class_array_count, class_pointer_count;
61 /* Low level lock which protects data structures in this module */
62 static mono_mutex_t classes_mutex;
64 /* Function supplied by the runtime to find classes by name using information from the AOT file */
65 static MonoGetClassFromName get_class_from_name = NULL;
67 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error);
68 static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
69 static gboolean can_access_type (MonoClass *access_klass, MonoClass *member_klass);
70 static MonoMethod* find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags);
71 static int generic_array_methods (MonoClass *klass);
72 static void setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos);
74 static MonoMethod* mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter);
75 static char* mono_assembly_name_from_token (MonoImage *image, guint32 type_token);
76 static void mono_field_resolve_type (MonoClassField *field, MonoError *error);
77 static guint32 mono_field_resolve_flags (MonoClassField *field);
78 static void mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup);
79 static void mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gklass);
81 static gboolean mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error);
82 static gpointer mono_class_get_exception_data (const MonoClass *klass);
86 We use gclass recording to allow recursive system f types to be referenced by a parent.
88 Given the following type hierarchy:
90 class TextBox : TextBoxBase<TextBox> {}
91 class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
92 class TextInput<T> : Input<T> where T: TextInput<T> {}
95 The runtime tries to load TextBoxBase<>.
96 To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
97 To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
98 To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
100 At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded
101 at this point, iow, both are registered in the type map and both and a NULL parent. This means
102 that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
104 To fix that what we do is to record all generic instantes created while resolving the parent of
105 any generic type definition and, after resolved, correct the parent field if needed.
108 static int record_gclass_instantiation;
109 static GSList *gclass_recorded_list;
110 typedef gboolean (*gclass_record_func) (MonoClass*, void*);
112 /* This TLS variable points to a GSList of classes which have setup_fields () executing */
113 static MonoNativeTlsKey setup_fields_tls_id;
115 static MonoNativeTlsKey init_pending_tls_id;
120 mono_locks_os_acquire (&classes_mutex, ClassesLock);
124 classes_unlock (void)
126 mono_locks_os_release (&classes_mutex, ClassesLock);
130 * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
133 enable_gclass_recording (void)
135 ++record_gclass_instantiation;
139 * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
142 disable_gclass_recording (gclass_record_func func, void *user_data)
144 GSList **head = &gclass_recorded_list;
146 g_assert (record_gclass_instantiation > 0);
147 --record_gclass_instantiation;
150 GSList *node = *head;
151 if (func ((MonoClass*)node->data, user_data)) {
153 g_slist_free_1 (node);
159 /* We automatically discard all recorded gclasses when disabled. */
160 if (!record_gclass_instantiation && gclass_recorded_list) {
161 g_slist_free (gclass_recorded_list);
162 gclass_recorded_list = NULL;
167 * mono_class_from_typeref:
168 * @image: a MonoImage
169 * @type_token: a TypeRef token
171 * Creates the MonoClass* structure representing the type defined by
172 * the typeref token valid inside @image.
173 * Returns: The MonoClass* representing the typeref token, NULL ifcould
177 mono_class_from_typeref (MonoImage *image, guint32 type_token)
180 MonoClass *klass = mono_class_from_typeref_checked (image, type_token, &error);
181 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
186 * mono_class_from_typeref_checked:
187 * @image: a MonoImage
188 * @type_token: a TypeRef token
189 * @error: error return code, if any.
191 * Creates the MonoClass* structure representing the type defined by
192 * the typeref token valid inside @image.
194 * Returns: The MonoClass* representing the typeref token, NULL if it could
195 * not be loaded with the @error value filled with the information about the
199 mono_class_from_typeref_checked (MonoImage *image, guint32 type_token, MonoError *error)
201 guint32 cols [MONO_TYPEREF_SIZE];
202 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
204 const char *name, *nspace;
205 MonoClass *res = NULL;
208 mono_error_init (error);
210 if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, error))
213 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
215 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
216 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
218 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
219 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
220 case MONO_RESOLUTION_SCOPE_MODULE:
222 LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
223 This is not the observed behavior of existing implementations.
224 The defacto behavior is that it's just a typedef in disguise.
226 /* a typedef in disguise */
227 res = mono_class_from_name_checked (image, nspace, name, error);
230 case MONO_RESOLUTION_SCOPE_MODULEREF:
231 module = mono_image_load_module_checked (image, idx, error);
233 res = mono_class_from_name_checked (module, nspace, name, error);
236 case MONO_RESOLUTION_SCOPE_TYPEREF: {
237 MonoClass *enclosing;
240 if (idx == mono_metadata_token_index (type_token)) {
241 mono_error_set_bad_image (error, image, "Image with self-referencing typeref token %08x.", type_token);
245 enclosing = mono_class_from_typeref_checked (image, MONO_TOKEN_TYPE_REF | idx, error);
246 return_val_if_nok (error, NULL);
248 if (enclosing->nested_classes_inited && enclosing->ext) {
249 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
250 for (tmp = enclosing->ext->nested_classes; tmp; tmp = tmp->next) {
251 res = (MonoClass *)tmp->data;
252 if (strcmp (res->name, name) == 0)
256 /* Don't call mono_class_init as we might've been called by it recursively */
257 int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
259 guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
260 guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
261 const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
263 if (strcmp (nname, name) == 0)
264 return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, error);
266 i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
269 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name);
272 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
276 if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) {
277 mono_error_set_bad_image (error, image, "Image with invalid assemblyref token %08x.", idx);
281 if (!image->references || !image->references [idx - 1])
282 mono_assembly_load_reference (image, idx - 1);
283 g_assert (image->references [idx - 1]);
285 /* If the assembly did not load, register this as a type load exception */
286 if (image->references [idx - 1] == REFERENCE_MISSING){
287 MonoAssemblyName aname;
290 mono_assembly_get_assemblyref (image, idx - 1, &aname);
291 human_name = mono_stringify_assembly_name (&aname);
292 mono_error_set_assembly_load_simple (error, human_name, image->assembly ? image->assembly->ref_only : FALSE);
296 res = mono_class_from_name_checked (image->references [idx - 1]->image, nspace, name, error);
299 /* Generic case, should be avoided for when a better error is possible. */
300 if (!res && mono_error_ok (error)) {
301 char *name = mono_class_name_from_token (image, type_token);
302 char *assembly = mono_assembly_name_from_token (image, type_token);
303 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
310 mono_image_memdup (MonoImage *image, void *data, guint size)
312 void *res = mono_image_alloc (image, size);
313 memcpy (res, data, size);
317 /* Copy everything mono_metadata_free_array free. */
319 mono_dup_array_type (MonoImage *image, MonoArrayType *a)
322 a = (MonoArrayType *)mono_image_memdup (image, a, sizeof (MonoArrayType));
324 a->sizes = (int *)mono_image_memdup (image, a->sizes, a->numsizes * sizeof (int));
326 a->lobounds = (int *)mono_image_memdup (image, a->lobounds, a->numlobounds * sizeof (int));
328 a = (MonoArrayType *)g_memdup (a, sizeof (MonoArrayType));
330 a->sizes = (int *)g_memdup (a->sizes, a->numsizes * sizeof (int));
332 a->lobounds = (int *)g_memdup (a->lobounds, a->numlobounds * sizeof (int));
337 /* Copy everything mono_metadata_free_method_signature free. */
339 mono_metadata_signature_deep_dup (MonoImage *image, MonoMethodSignature *sig)
343 sig = mono_metadata_signature_dup_full (image, sig);
345 sig->ret = mono_metadata_type_dup (image, sig->ret);
346 for (i = 0; i < sig->param_count; ++i)
347 sig->params [i] = mono_metadata_type_dup (image, sig->params [i]);
353 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
355 MonoAssembly *ta = klass->image->assembly;
358 name = mono_stringify_assembly_name (&ta->aname);
359 g_string_append_printf (str, ", %s", name);
364 mono_type_name_check_byref (MonoType *type, GString *str)
367 g_string_append_c (str, '&');
371 * mono_identifier_escape_type_name_chars:
372 * @str: a destination string
373 * @identifier: an IDENTIFIER in internal form
377 * The displayed form of the identifier is appended to str.
379 * The displayed form of an identifier has the characters ,+&*[]\
380 * that have special meaning in type names escaped with a preceeding
381 * backslash (\) character.
384 mono_identifier_escape_type_name_chars (GString* str, const char* identifier)
390 // reserve space for common case: there will be no escaped characters.
391 g_string_set_size(str, n + strlen(identifier));
392 g_string_set_size(str, n);
394 for (const char* s = identifier; *s != 0 ; s++) {
403 g_string_append_c (str, '\\');
404 g_string_append_c (str, *s);
407 g_string_append_c (str, *s);
415 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
416 MonoTypeNameFormat format)
420 switch (type->type) {
421 case MONO_TYPE_ARRAY: {
422 int i, rank = type->data.array->rank;
423 MonoTypeNameFormat nested_format;
425 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
426 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
428 mono_type_get_name_recurse (
429 &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
430 g_string_append_c (str, '[');
432 g_string_append_c (str, '*');
433 for (i = 1; i < rank; i++)
434 g_string_append_c (str, ',');
435 g_string_append_c (str, ']');
437 mono_type_name_check_byref (type, str);
439 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
440 _mono_type_get_assembly_name (type->data.array->eklass, str);
443 case MONO_TYPE_SZARRAY: {
444 MonoTypeNameFormat nested_format;
446 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
447 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
449 mono_type_get_name_recurse (
450 &type->data.klass->byval_arg, str, FALSE, nested_format);
451 g_string_append (str, "[]");
453 mono_type_name_check_byref (type, str);
455 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
456 _mono_type_get_assembly_name (type->data.klass, str);
459 case MONO_TYPE_PTR: {
460 MonoTypeNameFormat nested_format;
462 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
463 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
465 mono_type_get_name_recurse (
466 type->data.type, str, FALSE, nested_format);
467 g_string_append_c (str, '*');
469 mono_type_name_check_byref (type, str);
471 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
472 _mono_type_get_assembly_name (mono_class_from_mono_type (type->data.type), str);
477 if (!mono_generic_param_info (type->data.generic_param))
478 g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num);
480 g_string_append (str, mono_generic_param_info (type->data.generic_param)->name);
482 mono_type_name_check_byref (type, str);
486 klass = mono_class_from_mono_type (type);
487 if (klass->nested_in) {
488 mono_type_get_name_recurse (
489 &klass->nested_in->byval_arg, str, TRUE, format);
490 if (format == MONO_TYPE_NAME_FORMAT_IL)
491 g_string_append_c (str, '.');
493 g_string_append_c (str, '+');
494 } else if (*klass->name_space) {
495 if (format == MONO_TYPE_NAME_FORMAT_IL)
496 g_string_append (str, klass->name_space);
498 mono_identifier_escape_type_name_chars (str, klass->name_space);
499 g_string_append_c (str, '.');
501 if (format == MONO_TYPE_NAME_FORMAT_IL) {
502 char *s = strchr (klass->name, '`');
503 int len = s ? s - klass->name : strlen (klass->name);
504 g_string_append_len (str, klass->name, len);
506 mono_identifier_escape_type_name_chars (str, klass->name);
510 if (mono_class_is_ginst (klass)) {
511 MonoGenericClass *gclass = mono_class_get_generic_class (klass);
512 MonoGenericInst *inst = gclass->context.class_inst;
513 MonoTypeNameFormat nested_format;
516 nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
517 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
519 if (format == MONO_TYPE_NAME_FORMAT_IL)
520 g_string_append_c (str, '<');
522 g_string_append_c (str, '[');
523 for (i = 0; i < inst->type_argc; i++) {
524 MonoType *t = inst->type_argv [i];
527 g_string_append_c (str, ',');
528 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
529 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
530 g_string_append_c (str, '[');
531 mono_type_get_name_recurse (inst->type_argv [i], str, FALSE, nested_format);
532 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
533 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
534 g_string_append_c (str, ']');
536 if (format == MONO_TYPE_NAME_FORMAT_IL)
537 g_string_append_c (str, '>');
539 g_string_append_c (str, ']');
540 } else if (mono_class_is_gtd (klass) &&
541 (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
542 (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
545 if (format == MONO_TYPE_NAME_FORMAT_IL)
546 g_string_append_c (str, '<');
548 g_string_append_c (str, '[');
549 for (i = 0; i < mono_class_get_generic_container (klass)->type_argc; i++) {
551 g_string_append_c (str, ',');
552 g_string_append (str, mono_generic_container_get_param_info (mono_class_get_generic_container (klass), i)->name);
554 if (format == MONO_TYPE_NAME_FORMAT_IL)
555 g_string_append_c (str, '>');
557 g_string_append_c (str, ']');
560 mono_type_name_check_byref (type, str);
562 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
563 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
564 _mono_type_get_assembly_name (klass, str);
570 * mono_type_get_name_full:
572 * @format: the format for the return string.
575 * Returns: The string representation in a number of formats:
577 * if format is MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
578 * returned in the formatrequired by System.Reflection, this is the
579 * inverse of mono_reflection_parse_type ().
581 * if format is MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
582 * be used by the IL assembler.
584 * if format is MONO_TYPE_NAME_FORMAT_FULL_NAME
586 * if format is MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
589 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
593 result = g_string_new ("");
595 mono_type_get_name_recurse (type, result, FALSE, format);
597 return g_string_free (result, FALSE);
601 * mono_type_get_full_name:
604 * Returns: The string representation for type as required by System.Reflection.
605 * The inverse of mono_reflection_parse_type ().
608 mono_type_get_full_name (MonoClass *klass)
610 return mono_type_get_name_full (mono_class_get_type (klass), MONO_TYPE_NAME_FORMAT_REFLECTION);
614 * mono_type_get_name:
617 * Returns: The string representation for type as it would be represented in IL code.
620 mono_type_get_name (MonoType *type)
622 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
626 * mono_type_get_underlying_type:
629 * Returns: The MonoType for the underlying integer type if @type
630 * is an enum and byref is false, otherwise the type itself.
633 mono_type_get_underlying_type (MonoType *type)
635 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype && !type->byref)
636 return mono_class_enum_basetype (type->data.klass);
637 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype && !type->byref)
638 return mono_class_enum_basetype (type->data.generic_class->container_class);
643 * mono_class_is_open_constructed_type:
646 * Returns: TRUE if type represents a generics open constructed type.
647 * IOW, not all type parameters required for the instantiation have
648 * been provided or it's a generic type definition.
650 * An open constructed type means it's a non realizable type. Not to
651 * be mixed up with an abstract type - we can't cast or dispatch to
652 * an open type, for example.
655 mono_class_is_open_constructed_type (MonoType *t)
661 case MONO_TYPE_SZARRAY:
662 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
663 case MONO_TYPE_ARRAY:
664 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
666 return mono_class_is_open_constructed_type (t->data.type);
667 case MONO_TYPE_GENERICINST:
668 return t->data.generic_class->context.class_inst->is_open;
669 case MONO_TYPE_CLASS:
670 case MONO_TYPE_VALUETYPE:
671 return mono_class_is_gtd (t->data.klass);
678 This is a simple function to catch the most common bad instances of generic types.
679 Specially those that might lead to further failures in the runtime.
682 is_valid_generic_argument (MonoType *type)
684 switch (type->type) {
686 //case MONO_TYPE_TYPEDBYREF:
694 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
696 mono_error_init (error);
698 switch (type->type) {
699 case MONO_TYPE_MVAR: {
701 int num = mono_type_get_generic_param_num (type);
702 MonoGenericInst *inst = context->method_inst;
705 if (num >= inst->type_argc) {
706 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
707 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
708 num, info ? info->name : "", inst->type_argc);
712 if (!is_valid_generic_argument (inst->type_argv [num])) {
713 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
714 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
715 num, info ? info->name : "", inst->type_argv [num]->type);
719 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
720 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
721 * ->byref and ->attrs from @type are propagated to the returned type.
723 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
724 nt->byref = type->byref;
725 nt->attrs = type->attrs;
728 case MONO_TYPE_VAR: {
730 int num = mono_type_get_generic_param_num (type);
731 MonoGenericInst *inst = context->class_inst;
734 if (num >= inst->type_argc) {
735 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
736 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
737 num, info ? info->name : "", inst->type_argc);
740 if (!is_valid_generic_argument (inst->type_argv [num])) {
741 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
742 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
743 num, info ? info->name : "", inst->type_argv [num]->type);
746 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
747 nt->byref = type->byref;
748 nt->attrs = type->attrs;
751 case MONO_TYPE_SZARRAY: {
752 MonoClass *eclass = type->data.klass;
753 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
754 if (!inflated || !mono_error_ok (error))
756 nt = mono_metadata_type_dup (image, type);
757 nt->data.klass = mono_class_from_mono_type (inflated);
758 mono_metadata_free_type (inflated);
761 case MONO_TYPE_ARRAY: {
762 MonoClass *eclass = type->data.array->eklass;
763 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
764 if (!inflated || !mono_error_ok (error))
766 nt = mono_metadata_type_dup (image, type);
767 nt->data.array->eklass = mono_class_from_mono_type (inflated);
768 mono_metadata_free_type (inflated);
771 case MONO_TYPE_GENERICINST: {
772 MonoGenericClass *gclass = type->data.generic_class;
773 MonoGenericInst *inst;
775 if (!gclass->context.class_inst->is_open)
778 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
779 return_val_if_nok (error, NULL);
781 if (inst != gclass->context.class_inst)
782 gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
784 if (gclass == type->data.generic_class)
787 nt = mono_metadata_type_dup (image, type);
788 nt->data.generic_class = gclass;
791 case MONO_TYPE_CLASS:
792 case MONO_TYPE_VALUETYPE: {
793 MonoClass *klass = type->data.klass;
794 MonoGenericContainer *container = mono_class_try_get_generic_container (klass);
795 MonoGenericInst *inst;
796 MonoGenericClass *gclass = NULL;
802 /* We can't use context->class_inst directly, since it can have more elements */
803 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
804 return_val_if_nok (error, NULL);
806 if (inst == container->context.class_inst)
809 gclass = mono_metadata_lookup_generic_class (klass, inst, image_is_dynamic (klass->image));
811 nt = mono_metadata_type_dup (image, type);
812 nt->type = MONO_TYPE_GENERICINST;
813 nt->data.generic_class = gclass;
823 mono_generic_class_get_context (MonoGenericClass *gclass)
825 return &gclass->context;
829 mono_class_get_context (MonoClass *klass)
831 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
832 return gklass ? mono_generic_class_get_context (gklass) : NULL;
836 * mono_class_inflate_generic_type_with_mempool:
837 * @mempool: a mempool
839 * @context: a generics context
840 * @error: error context
842 * The same as mono_class_inflate_generic_type, but allocates the MonoType
843 * from mempool if it is non-NULL. If it is NULL, the MonoType is
844 * allocated on the heap and is owned by the caller.
845 * The returned type can potentially be the same as TYPE, so it should not be
846 * modified by the caller, and it should be freed using mono_metadata_free_type ().
849 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
851 MonoType *inflated = NULL;
852 mono_error_init (error);
855 inflated = inflate_generic_type (image, type, context, error);
856 return_val_if_nok (error, NULL);
859 MonoType *shared = mono_metadata_get_shared_type (type);
864 return mono_metadata_type_dup (image, type);
868 mono_stats.inflated_type_count++;
873 * mono_class_inflate_generic_type:
875 * @context: a generics context
877 * If @type is a generic type and @context is not NULL, instantiate it using the
878 * generics context @context.
880 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
881 * on the heap and is owned by the caller. Returns NULL on error.
883 * @deprecated Please use mono_class_inflate_generic_type_checked instead
886 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
890 result = mono_class_inflate_generic_type_checked (type, context, &error);
891 mono_error_cleanup (&error);
896 * mono_class_inflate_generic_type:
898 * @context: a generics context
899 * @error: error context to use
901 * If @type is a generic type and @context is not NULL, instantiate it using the
902 * generics context @context.
904 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
905 * on the heap and is owned by the caller.
908 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
910 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
914 * mono_class_inflate_generic_type_no_copy:
916 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
920 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
922 MonoType *inflated = NULL;
924 mono_error_init (error);
926 inflated = inflate_generic_type (image, type, context, error);
927 return_val_if_nok (error, NULL);
933 mono_stats.inflated_type_count++;
938 * mono_class_inflate_generic_class:
940 * Inflate the class @gklass with @context. Set @error on failure.
943 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
948 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
949 return_val_if_nok (error, NULL);
951 res = mono_class_from_mono_type (inflated);
952 mono_metadata_free_type (inflated);
957 static MonoGenericContext
958 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
960 MonoGenericInst *class_inst = NULL;
961 MonoGenericInst *method_inst = NULL;
962 MonoGenericContext res = { NULL, NULL };
964 mono_error_init (error);
966 if (context->class_inst) {
967 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
968 if (!mono_error_ok (error))
972 if (context->method_inst) {
973 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
974 if (!mono_error_ok (error))
978 res.class_inst = class_inst;
979 res.method_inst = method_inst;
985 * mono_class_inflate_generic_method:
986 * @method: a generic method
987 * @context: a generics context
989 * Instantiate the generic method @method using the generics context @context.
991 * Returns: The new instantiated method
994 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
996 return mono_class_inflate_generic_method_full (method, NULL, context);
1000 mono_class_inflate_generic_method_checked (MonoMethod *method, MonoGenericContext *context, MonoError *error)
1002 return mono_class_inflate_generic_method_full_checked (method, NULL, context, error);
1006 * mono_class_inflate_generic_method_full:
1008 * Instantiate method @method with the generic context @context.
1009 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
1010 * Use mono_method_signature () and mono_method_get_header () to get the correct values.
1013 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
1016 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
1017 if (!mono_error_ok (&error))
1018 /*FIXME do proper error handling - on this case, kill this function. */
1019 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
1025 * mono_class_inflate_generic_method_full_checked:
1026 * Same as mono_class_inflate_generic_method_full but return failure using @error.
1029 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
1032 MonoMethodInflated *iresult, *cached;
1033 MonoMethodSignature *sig;
1034 MonoGenericContext tmp_context;
1036 mono_error_init (error);
1038 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1039 while (method->is_inflated) {
1040 MonoGenericContext *method_context = mono_method_get_context (method);
1041 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1043 tmp_context = inflate_generic_context (method_context, context, error);
1044 return_val_if_nok (error, NULL);
1046 context = &tmp_context;
1048 if (mono_metadata_generic_context_equal (method_context, context))
1051 method = imethod->declaring;
1055 * A method only needs to be inflated if the context has argument for which it is
1058 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1059 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1062 if (!((method->is_generic && context->method_inst) ||
1063 (mono_class_is_gtd (method->klass) && context->class_inst)))
1066 iresult = g_new0 (MonoMethodInflated, 1);
1067 iresult->context = *context;
1068 iresult->declaring = method;
1070 if (!context->method_inst && method->is_generic)
1071 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1073 if (!context->class_inst) {
1074 g_assert (!mono_class_is_ginst (iresult->declaring->klass));
1075 if (mono_class_is_gtd (iresult->declaring->klass))
1076 iresult->context.class_inst = mono_class_get_generic_container (iresult->declaring->klass)->context.class_inst;
1078 /* This can happen with some callers like mono_object_get_virtual_method () */
1079 if (!mono_class_is_gtd (iresult->declaring->klass) && !mono_class_is_ginst (iresult->declaring->klass))
1080 iresult->context.class_inst = NULL;
1082 MonoImageSet *set = mono_metadata_get_image_set_for_method (iresult);
1085 mono_image_set_lock (set);
1086 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1087 mono_image_set_unlock (set);
1091 return (MonoMethod*)cached;
1094 mono_stats.inflated_method_count++;
1096 inflated_methods_size += sizeof (MonoMethodInflated);
1098 sig = mono_method_signature (method);
1100 char *name = mono_type_get_full_name (method->klass);
1101 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1107 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1109 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1112 result = (MonoMethod *) iresult;
1113 result->is_inflated = TRUE;
1114 result->is_generic = FALSE;
1115 result->sre_method = FALSE;
1116 result->signature = NULL;
1118 if (method->wrapper_type) {
1119 MonoMethodWrapper *mw = (MonoMethodWrapper*)method;
1120 MonoMethodWrapper *resw = (MonoMethodWrapper*)result;
1121 int len = GPOINTER_TO_INT (((void**)mw->method_data) [0]);
1123 resw->method_data = (void **)g_malloc (sizeof (gpointer) * (len + 1));
1124 memcpy (resw->method_data, mw->method_data, sizeof (gpointer) * (len + 1));
1127 if (iresult->context.method_inst) {
1128 /* Set the generic_container of the result to the generic_container of method */
1129 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1131 if (generic_container && iresult->context.method_inst == generic_container->context.method_inst) {
1132 result->is_generic = 1;
1133 mono_method_set_generic_container (result, generic_container);
1138 MonoGenericClass *gklass_hint = mono_class_try_get_generic_class (klass_hint);
1139 if (gklass_hint && (gklass_hint->container_class != method->klass || gklass_hint->context.class_inst != context->class_inst))
1143 if (mono_class_is_gtd (method->klass))
1144 result->klass = klass_hint;
1146 if (!result->klass) {
1147 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1148 if (!mono_error_ok (error))
1151 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1153 mono_metadata_free_type (inflated);
1157 * FIXME: This should hold, but it doesn't:
1159 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1160 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1161 * g_assert (result->is_generic);
1164 * Fixing this here causes other things to break, hence a very
1165 * ugly hack in mini-trampolines.c - see
1166 * is_generic_method_definition().
1170 mono_image_set_lock (set);
1171 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1173 g_hash_table_insert (set->gmethod_cache, iresult, iresult);
1174 iresult->owner = set;
1177 mono_image_set_unlock (set);
1179 return (MonoMethod*)cached;
1187 * mono_get_inflated_method:
1189 * Obsolete. We keep it around since it's mentioned in the public API.
1192 mono_get_inflated_method (MonoMethod *method)
1198 * mono_method_get_context_general:
1200 * @uninflated: handle uninflated methods?
1202 * Returns the generic context of a method or NULL if it doesn't have
1203 * one. For an inflated method that's the context stored in the
1204 * method. Otherwise it's in the method's generic container or in the
1205 * generic container of the method's class.
1208 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1210 if (method->is_inflated) {
1211 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1212 return &imethod->context;
1216 if (method->is_generic)
1217 return &(mono_method_get_generic_container (method)->context);
1218 if (mono_class_is_gtd (method->klass))
1219 return &mono_class_get_generic_container (method->klass)->context;
1224 * mono_method_get_context:
1227 * Returns the generic context for method if it's inflated, otherwise
1231 mono_method_get_context (MonoMethod *method)
1233 return mono_method_get_context_general (method, FALSE);
1237 * mono_method_get_generic_container:
1239 * Returns the generic container of METHOD, which should be a generic method definition.
1240 * Returns NULL if METHOD is not a generic method definition.
1241 * LOCKING: Acquires the loader lock.
1243 MonoGenericContainer*
1244 mono_method_get_generic_container (MonoMethod *method)
1246 MonoGenericContainer *container;
1248 if (!method->is_generic)
1251 container = (MonoGenericContainer *)mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1252 g_assert (container);
1258 * mono_method_set_generic_container:
1260 * Sets the generic container of METHOD to CONTAINER.
1261 * LOCKING: Acquires the image lock.
1264 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1266 g_assert (method->is_generic);
1268 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1272 * mono_class_find_enum_basetype:
1273 * @class: The enum class
1275 * Determine the basetype of an enum by iterating through its fields. We do this
1276 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1279 mono_class_find_enum_basetype (MonoClass *klass, MonoError *error)
1281 MonoGenericContainer *container = NULL;
1282 MonoImage *m = klass->image;
1283 const int top = klass->field.count;
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 klass->field.count = gtd->field.count;
1448 mono_loader_unlock ();
1451 top = klass->field.count;
1453 fields = (MonoClassField *)mono_class_alloc0 (klass, sizeof (MonoClassField) * top);
1456 * Fetch all the field information.
1458 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 = klass->field.count;
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 = klass->field.count;
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 = gklass->method.count;
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) {
2267 klass->method.count ++;
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 = klass->method.count;
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 klass->method.count = 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 < klass->method.count);
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 for (i = 0; i < gklass->method.count; ++i) {
2441 if (gklass->methods [i] == method) {
2442 if (klass->methods) {
2443 return klass->methods [i];
2446 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], klass, mono_class_get_context (klass), &error);
2447 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2457 * mono_class_get_vtable_entry:
2459 * Returns klass->vtable [offset], computing it if neccesary. Returns NULL on failure.
2460 * LOCKING: Acquires the loader lock.
2463 mono_class_get_vtable_entry (MonoClass *klass, int offset)
2467 if (klass->rank == 1) {
2469 * szarrays do not overwrite any methods of Array, so we can avoid
2470 * initializing their vtables in some cases.
2472 mono_class_setup_vtable (klass->parent);
2473 if (offset < klass->parent->vtable_size)
2474 return klass->parent->vtable [offset];
2477 if (mono_class_is_ginst (klass)) {
2479 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2480 mono_class_setup_vtable (gklass);
2481 m = gklass->vtable [offset];
2483 m = mono_class_inflate_generic_method_full_checked (m, klass, mono_class_get_context (klass), &error);
2484 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2486 mono_class_setup_vtable (klass);
2487 if (mono_class_has_failure (klass))
2489 m = klass->vtable [offset];
2496 * mono_class_get_vtable_size:
2498 * Return the vtable size for KLASS.
2501 mono_class_get_vtable_size (MonoClass *klass)
2503 mono_class_setup_vtable (klass);
2505 return klass->vtable_size;
2509 * mono_class_setup_properties:
2511 * Initialize klass->ext.property and klass->ext.properties.
2513 * This method can fail the class.
2516 mono_class_setup_properties (MonoClass *klass)
2518 guint startm, endm, i, j;
2519 guint32 cols [MONO_PROPERTY_SIZE];
2520 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2521 MonoProperty *properties;
2525 if (klass->ext && klass->ext->properties)
2528 if (mono_class_is_ginst (klass)) {
2529 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2531 mono_class_init (gklass);
2532 mono_class_setup_properties (gklass);
2533 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2536 properties = mono_class_new0 (klass, MonoProperty, gklass->ext->property.count + 1);
2538 for (i = 0; i < gklass->ext->property.count; i++) {
2540 MonoProperty *prop = &properties [i];
2542 *prop = gklass->ext->properties [i];
2545 prop->get = mono_class_inflate_generic_method_full_checked (
2546 prop->get, klass, mono_class_get_context (klass), &error);
2548 prop->set = mono_class_inflate_generic_method_full_checked (
2549 prop->set, klass, mono_class_get_context (klass), &error);
2551 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2552 prop->parent = klass;
2555 first = gklass->ext->property.first;
2556 count = gklass->ext->property.count;
2558 first = mono_metadata_properties_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2559 count = last - first;
2562 mono_class_setup_methods (klass);
2563 if (mono_class_has_failure (klass))
2567 properties = (MonoProperty *)mono_class_alloc0 (klass, sizeof (MonoProperty) * count);
2568 for (i = first; i < last; ++i) {
2569 mono_metadata_decode_table_row (klass->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2570 properties [i - first].parent = klass;
2571 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2572 properties [i - first].name = mono_metadata_string_heap (klass->image, cols [MONO_PROPERTY_NAME]);
2574 startm = mono_metadata_methods_from_property (klass->image, i, &endm);
2575 int first_idx = mono_class_get_first_method_idx (klass);
2576 for (j = startm; j < endm; ++j) {
2579 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2581 if (klass->image->uncompressed_metadata) {
2583 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2584 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2585 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2587 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - first_idx];
2590 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2591 case METHOD_SEMANTIC_SETTER:
2592 properties [i - first].set = method;
2594 case METHOD_SEMANTIC_GETTER:
2595 properties [i - first].get = method;
2604 mono_class_alloc_ext (klass);
2606 mono_image_lock (klass->image);
2608 if (klass->ext->properties) {
2609 /* We leak 'properties' which was allocated from the image mempool */
2610 mono_image_unlock (klass->image);
2614 klass->ext->property.first = first;
2615 klass->ext->property.count = count;
2617 /* Flush any pending writes as we do double checked locking on klass->ext->properties */
2618 mono_memory_barrier ();
2620 /* Leave this assignment as the last op in the function */
2621 klass->ext->properties = properties;
2623 mono_image_unlock (klass->image);
2627 inflate_method_listz (MonoMethod **methods, MonoClass *klass, MonoGenericContext *context)
2629 MonoMethod **om, **retval;
2632 for (om = methods, count = 0; *om; ++om, ++count)
2635 retval = g_new0 (MonoMethod*, count + 1);
2637 for (om = methods, count = 0; *om; ++om, ++count) {
2639 retval [count] = mono_class_inflate_generic_method_full_checked (*om, klass, context, &error);
2640 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2646 /*This method can fail the class.*/
2648 mono_class_setup_events (MonoClass *klass)
2651 guint startm, endm, i, j;
2652 guint32 cols [MONO_EVENT_SIZE];
2653 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2657 if (klass->ext && klass->ext->events)
2660 if (mono_class_is_ginst (klass)) {
2661 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2662 MonoGenericContext *context = NULL;
2664 mono_class_setup_events (gklass);
2665 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2668 first = gklass->ext->event.first;
2669 count = gklass->ext->event.count;
2671 events = mono_class_new0 (klass, MonoEvent, count);
2674 context = mono_class_get_context (klass);
2676 for (i = 0; i < count; i++) {
2678 MonoEvent *event = &events [i];
2679 MonoEvent *gevent = &gklass->ext->events [i];
2681 mono_error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2683 event->parent = klass;
2684 event->name = gevent->name;
2685 event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, klass, context, &error) : NULL;
2686 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2687 event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, klass, context, &error) : NULL;
2688 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2689 event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, klass, context, &error) : NULL;
2690 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2692 #ifndef MONO_SMALL_CONFIG
2693 event->other = gevent->other ? inflate_method_listz (gevent->other, klass, context) : NULL;
2695 event->attrs = gevent->attrs;
2698 first = mono_metadata_events_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2699 count = last - first;
2702 mono_class_setup_methods (klass);
2703 if (mono_class_has_failure (klass)) {
2708 events = (MonoEvent *)mono_class_alloc0 (klass, sizeof (MonoEvent) * count);
2709 for (i = first; i < last; ++i) {
2710 MonoEvent *event = &events [i - first];
2712 mono_metadata_decode_table_row (klass->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2713 event->parent = klass;
2714 event->attrs = cols [MONO_EVENT_FLAGS];
2715 event->name = mono_metadata_string_heap (klass->image, cols [MONO_EVENT_NAME]);
2717 startm = mono_metadata_methods_from_event (klass->image, i, &endm);
2718 int first_idx = mono_class_get_first_method_idx (klass);
2719 for (j = startm; j < endm; ++j) {
2722 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2724 if (klass->image->uncompressed_metadata) {
2726 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2727 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2728 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2730 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - first_idx];
2733 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2734 case METHOD_SEMANTIC_ADD_ON:
2735 event->add = method;
2737 case METHOD_SEMANTIC_REMOVE_ON:
2738 event->remove = method;
2740 case METHOD_SEMANTIC_FIRE:
2741 event->raise = method;
2743 case METHOD_SEMANTIC_OTHER: {
2744 #ifndef MONO_SMALL_CONFIG
2747 if (event->other == NULL) {
2748 event->other = g_new0 (MonoMethod*, 2);
2750 while (event->other [n])
2752 event->other = (MonoMethod **)g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2754 event->other [n] = method;
2755 /* NULL terminated */
2756 event->other [n + 1] = NULL;
2767 mono_class_alloc_ext (klass);
2769 mono_image_lock (klass->image);
2771 if (klass->ext->events) {
2772 mono_image_unlock (klass->image);
2776 klass->ext->event.first = first;
2777 klass->ext->event.count = count;
2779 /* Flush any pending writes as we do double checked locking on klass->ext.events */
2780 mono_memory_barrier ();
2782 /* Leave this assignment as the last op in the function */
2783 klass->ext->events = events;
2785 mono_image_unlock (klass->image);
2789 * Global pool of interface IDs, represented as a bitset.
2790 * LOCKING: Protected by the classes lock.
2792 static MonoBitSet *global_interface_bitset = NULL;
2795 * mono_unload_interface_ids:
2796 * @bitset: bit set of interface IDs
2798 * When an image is unloaded, the interface IDs associated with
2799 * the image are put back in the global pool of IDs so the numbers
2803 mono_unload_interface_ids (MonoBitSet *bitset)
2806 mono_bitset_sub (global_interface_bitset, bitset);
2811 mono_unload_interface_id (MonoClass *klass)
2813 if (global_interface_bitset && klass->interface_id) {
2815 mono_bitset_clear (global_interface_bitset, klass->interface_id);
2821 * mono_get_unique_iid:
2824 * Assign a unique integer ID to the interface represented by @class.
2825 * The ID will positive and as small as possible.
2826 * LOCKING: Acquires the classes lock.
2827 * Returns: The new ID.
2830 mono_get_unique_iid (MonoClass *klass)
2834 g_assert (MONO_CLASS_IS_INTERFACE (klass));
2838 if (!global_interface_bitset) {
2839 global_interface_bitset = mono_bitset_new (128, 0);
2842 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2844 int old_size = mono_bitset_size (global_interface_bitset);
2845 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2846 mono_bitset_free (global_interface_bitset);
2847 global_interface_bitset = new_set;
2850 mono_bitset_set (global_interface_bitset, iid);
2851 /* set the bit also in the per-image set */
2852 if (!mono_class_is_ginst (klass)) {
2853 if (klass->image->interface_bitset) {
2854 if (iid >= mono_bitset_size (klass->image->interface_bitset)) {
2855 MonoBitSet *new_set = mono_bitset_clone (klass->image->interface_bitset, iid + 1);
2856 mono_bitset_free (klass->image->interface_bitset);
2857 klass->image->interface_bitset = new_set;
2860 klass->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2862 mono_bitset_set (klass->image->interface_bitset, iid);
2867 #ifndef MONO_SMALL_CONFIG
2868 if (mono_print_vtable) {
2870 char *type_name = mono_type_full_name (&klass->byval_arg);
2871 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
2872 if (gklass && !gklass->context.class_inst->is_open) {
2873 generic_id = gklass->context.class_inst->id;
2874 g_assert (generic_id != 0);
2878 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, klass->image->name, type_name, generic_id);
2883 g_assert (iid <= 65535);
2888 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2893 mono_class_setup_interfaces (klass, error);
2894 return_if_nok (error);
2896 for (i = 0; i < klass->interface_count; i++) {
2897 ic = klass->interfaces [i];
2900 *res = g_ptr_array_new ();
2901 g_ptr_array_add (*res, ic);
2902 mono_class_init (ic);
2903 if (mono_class_has_failure (ic)) {
2904 mono_error_set_type_load_class (error, ic, "Error Loading class");
2908 collect_implemented_interfaces_aux (ic, res, error);
2909 return_if_nok (error);
2914 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2916 GPtrArray *res = NULL;
2918 collect_implemented_interfaces_aux (klass, &res, error);
2919 if (!mono_error_ok (error)) {
2921 g_ptr_array_free (res, TRUE);
2928 compare_interface_ids (const void *p_key, const void *p_element) {
2929 const MonoClass *key = (const MonoClass *)p_key;
2930 const MonoClass *element = *(const MonoClass **)p_element;
2932 return (key->interface_id - element->interface_id);
2935 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2937 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2938 MonoClass **result = (MonoClass **)mono_binary_search (
2940 klass->interfaces_packed,
2941 klass->interface_offsets_count,
2942 sizeof (MonoClass *),
2943 compare_interface_ids);
2945 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2952 * mono_class_interface_offset_with_variance:
2954 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2955 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2957 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2959 * FIXME figure out MS disambiguation rules and fix this function.
2962 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2963 int i = mono_class_interface_offset (klass, itf);
2964 *non_exact_match = FALSE;
2968 if (!mono_class_has_variant_generic_params (itf))
2971 for (i = 0; i < klass->interface_offsets_count; i++) {
2972 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2973 *non_exact_match = TRUE;
2974 return klass->interface_offsets_packed [i];
2982 print_implemented_interfaces (MonoClass *klass) {
2985 GPtrArray *ifaces = NULL;
2987 int ancestor_level = 0;
2989 name = mono_type_get_full_name (klass);
2990 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2993 for (i = 0; i < klass->interface_offsets_count; i++)
2994 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2995 klass->interfaces_packed [i]->interface_id,
2996 klass->interface_offsets_packed [i],
2997 klass->interfaces_packed [i]->method.count,
2998 klass->interfaces_packed [i]->name_space,
2999 klass->interfaces_packed [i]->name );
3000 printf ("Interface flags: ");
3001 for (i = 0; i <= klass->max_interface_id; i++)
3002 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
3003 printf ("(%d,T)", i);
3005 printf ("(%d,F)", i);
3007 printf ("Dump interface flags:");
3008 #ifdef COMPRESSED_INTERFACE_BITMAP
3010 const uint8_t* p = klass->interface_bitmap;
3011 i = klass->max_interface_id;
3013 printf (" %d x 00 %02X", p [0], p [1]);
3019 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
3020 printf (" %02X", klass->interface_bitmap [i]);
3023 while (klass != NULL) {
3024 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
3025 ifaces = mono_class_get_implemented_interfaces (klass, &error);
3026 if (!mono_error_ok (&error)) {
3027 printf (" Type failed due to %s\n", mono_error_get_message (&error));
3028 mono_error_cleanup (&error);
3029 } else if (ifaces) {
3030 for (i = 0; i < ifaces->len; i++) {
3031 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3032 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
3033 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3035 mono_class_interface_offset (klass, ic),
3040 g_ptr_array_free (ifaces, TRUE);
3043 klass = klass->parent;
3048 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
3051 args [0] = &arg0->byval_arg;
3053 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
3057 array_class_get_if_rank (MonoClass *klass, guint rank)
3059 return rank ? mono_array_class_get (klass, rank) : klass;
3063 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
3065 valuetype_types [0] = eclass;
3066 if (eclass == mono_defaults.int16_class)
3067 valuetype_types [1] = mono_defaults.uint16_class;
3068 else if (eclass == mono_defaults.uint16_class)
3069 valuetype_types [1] = mono_defaults.int16_class;
3070 else if (eclass == mono_defaults.int32_class)
3071 valuetype_types [1] = mono_defaults.uint32_class;
3072 else if (eclass == mono_defaults.uint32_class)
3073 valuetype_types [1] = mono_defaults.int32_class;
3074 else if (eclass == mono_defaults.int64_class)
3075 valuetype_types [1] = mono_defaults.uint64_class;
3076 else if (eclass == mono_defaults.uint64_class)
3077 valuetype_types [1] = mono_defaults.int64_class;
3078 else if (eclass == mono_defaults.byte_class)
3079 valuetype_types [1] = mono_defaults.sbyte_class;
3080 else if (eclass == mono_defaults.sbyte_class)
3081 valuetype_types [1] = mono_defaults.byte_class;
3082 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
3083 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
3086 static GENERATE_GET_CLASS_WITH_CACHE (generic_icollection, System.Collections.Generic, ICollection`1)
3087 static GENERATE_GET_CLASS_WITH_CACHE (generic_ienumerable, System.Collections.Generic, IEnumerable`1)
3088 static GENERATE_GET_CLASS_WITH_CACHE (generic_ienumerator, System.Collections.Generic, IEnumerator`1)
3089 static GENERATE_GET_CLASS_WITH_CACHE (generic_ireadonlylist, System.Collections.Generic, IReadOnlyList`1)
3090 static GENERATE_GET_CLASS_WITH_CACHE (generic_ireadonlycollection, System.Collections.Generic, IReadOnlyCollection`1)
3092 /* this won't be needed once bug #325495 is completely fixed
3093 * though we'll need something similar to know which interfaces to allow
3094 * in arrays when they'll be lazyly created
3096 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
3097 * MS returns diferrent types based on which instance is called. For example:
3098 * object obj = new byte[10][];
3099 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
3100 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
3103 * Fixing this should kill quite some code, save some bits and improve compatibility.
3106 get_implicit_generic_array_interfaces (MonoClass *klass, int *num, int *is_enumerator)
3108 MonoClass *eclass = klass->element_class;
3109 MonoClass* generic_icollection_class;
3110 MonoClass* generic_ienumerable_class;
3111 MonoClass* generic_ienumerator_class;
3112 MonoClass* generic_ireadonlylist_class;
3113 MonoClass* generic_ireadonlycollection_class;
3114 MonoClass *valuetype_types[2] = { NULL, NULL };
3115 MonoClass **interfaces = NULL;
3116 int i, nifaces, interface_count, real_count, original_rank;
3118 gboolean internal_enumerator;
3119 gboolean eclass_is_valuetype;
3121 if (!mono_defaults.generic_ilist_class) {
3125 internal_enumerator = FALSE;
3126 eclass_is_valuetype = FALSE;
3127 original_rank = eclass->rank;
3128 if (klass->byval_arg.type != MONO_TYPE_SZARRAY) {
3129 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
3130 if (gklass && klass->nested_in == mono_defaults.array_class && strcmp (klass->name, "InternalEnumerator`1") == 0) {
3132 * For a Enumerator<T[]> we need to get the list of interfaces for T.
3134 eclass = mono_class_from_mono_type (gklass->context.class_inst->type_argv [0]);
3135 original_rank = eclass->rank;
3137 eclass = eclass->element_class;
3138 internal_enumerator = TRUE;
3139 *is_enumerator = TRUE;
3147 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
3148 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
3150 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
3152 generic_icollection_class = mono_class_get_generic_icollection_class ();
3153 generic_ienumerable_class = mono_class_get_generic_ienumerable_class ();
3154 generic_ienumerator_class = mono_class_get_generic_ienumerator_class ();
3155 generic_ireadonlylist_class = mono_class_get_generic_ireadonlylist_class ();
3156 generic_ireadonlycollection_class = mono_class_get_generic_ireadonlycollection_class ();
3158 mono_class_init (eclass);
3161 * Arrays in 2.0 need to implement a number of generic interfaces
3162 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
3163 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
3164 * We collect the types needed to build the
3165 * instantiations in interfaces at intervals of 3/5, because 3/5 are
3166 * the generic interfaces needed to implement.
3168 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
3169 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
3171 if (eclass->valuetype) {
3172 nifaces = generic_ireadonlylist_class ? 5 : 3;
3173 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
3175 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
3176 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
3177 if (internal_enumerator) {
3179 if (valuetype_types [1])
3183 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3184 interfaces [0] = valuetype_types [0];
3185 if (valuetype_types [1])
3186 interfaces [nifaces] = valuetype_types [1];
3188 eclass_is_valuetype = TRUE;
3191 int idepth = eclass->idepth;
3192 if (!internal_enumerator)
3194 nifaces = generic_ireadonlylist_class ? 2 : 3;
3196 // FIXME: This doesn't seem to work/required for generic params
3197 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
3198 mono_class_setup_interface_offsets (eclass);
3200 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
3201 /* we add object for interfaces and the supertypes for the other
3202 * types. The last of the supertypes is the element class itself which we
3203 * already created the explicit interfaces for (so we include it for IEnumerator
3204 * and exclude it for arrays).
3206 if (MONO_CLASS_IS_INTERFACE (eclass))
3209 interface_count += idepth;
3210 if (eclass->rank && eclass->element_class->valuetype) {
3211 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3212 if (valuetype_types [1])
3215 /* IList, ICollection, IEnumerable, IReadOnlyList */
3216 interface_count *= nifaces;
3217 real_count = interface_count;
3218 if (internal_enumerator) {
3219 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3220 if (valuetype_types [1])
3223 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3224 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3225 interfaces [0] = mono_defaults.object_class;
3229 for (i = 0; i < idepth; i++) {
3230 mono_class_init (eclass->supertypes [i]);
3231 interfaces [j] = eclass->supertypes [i];
3235 if (all_interfaces) {
3236 for (i = 0; i < eclass->interface_offsets_count; i++) {
3237 interfaces [j] = eclass->interfaces_packed [i];
3241 for (i = 0; i < eclass->interface_count; i++) {
3242 interfaces [j] = eclass->interfaces [i];
3246 if (valuetype_types [1]) {
3247 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3252 /* instantiate the generic interfaces */
3253 for (i = 0; i < interface_count; i += nifaces) {
3254 MonoClass *iface = interfaces [i];
3256 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3257 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3259 if (eclass->valuetype) {
3260 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3261 if (generic_ireadonlylist_class) {
3262 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3263 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3266 if (!generic_ireadonlylist_class)
3267 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3270 if (internal_enumerator) {
3272 /* instantiate IEnumerator<iface> */
3273 for (i = 0; i < interface_count; i++) {
3274 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3276 j = interface_count;
3277 if (!eclass_is_valuetype) {
3278 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3279 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3282 for (i = 0; i < eclass->idepth; i++) {
3283 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3287 for (i = 0; i < eclass->interface_offsets_count; i++) {
3288 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3292 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3294 if (valuetype_types [1])
3295 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3299 char *type_name = mono_type_get_name_full (&klass->byval_arg, 0);
3300 for (i = 0; i < real_count; ++i) {
3301 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3302 g_print ("%s implements %s\n", type_name, name);
3313 find_array_interface (MonoClass *klass, const char *name)
3316 for (i = 0; i < klass->interface_count; ++i) {
3317 if (strcmp (klass->interfaces [i]->name, name) == 0)
3324 * Return the number of virtual methods.
3325 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3326 * Return -1 on failure.
3327 * FIXME It would be nice if this information could be cached somewhere.
3330 count_virtual_methods (MonoClass *klass)
3334 klass = mono_class_get_generic_type_definition (klass); /*We can find this information by looking at the GTD*/
3336 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
3337 mono_class_setup_methods (klass);
3338 if (mono_class_has_failure (klass))
3341 for (i = 0; i < klass->method.count; ++i) {
3342 flags = klass->methods [i]->flags;
3343 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3347 int first_idx = mono_class_get_first_method_idx (klass);
3348 for (i = 0; i < klass->method.count; ++i) {
3349 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
3351 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3359 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3367 m = (l + num_ifaces) / 2;
3368 if (interfaces_full [m] == ic)
3370 if (l == num_ifaces)
3372 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3381 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3383 int i = find_interface (num_ifaces, interfaces_full, ic);
3385 return interface_offsets_full [i];
3390 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3392 int i = find_interface (num_ifaces, interfaces_full, ic);
3396 interface_offsets_full [i] = offset;
3399 for (i = 0; i < num_ifaces; ++i) {
3400 if (interfaces_full [i]) {
3402 if (interfaces_full [i]->interface_id < ic->interface_id)
3405 while (end < num_ifaces && interfaces_full [end]) end++;
3406 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3407 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3409 interfaces_full [i] = ic;
3410 interface_offsets_full [i] = offset;
3416 #ifdef COMPRESSED_INTERFACE_BITMAP
3419 * Compressed interface bitmap design.
3421 * Interface bitmaps take a large amount of memory, because their size is
3422 * linear with the maximum interface id assigned in the process (each interface
3423 * is assigned a unique id as it is loaded). The number of interface classes
3424 * is high because of the many implicit interfaces implemented by arrays (we'll
3425 * need to lazy-load them in the future).
3426 * Most classes implement a very small number of interfaces, so the bitmap is
3427 * sparse. This bitmap needs to be checked by interface casts, so access to the
3428 * needed bit must be fast and doable with few jit instructions.
3430 * The current compression format is as follows:
3431 * *) it is a sequence of one or more two-byte elements
3432 * *) the first byte in the element is the count of empty bitmap bytes
3433 * at the current bitmap position
3434 * *) the second byte in the element is an actual bitmap byte at the current
3437 * As an example, the following compressed bitmap bytes:
3438 * 0x07 0x01 0x00 0x7
3439 * correspond to the following bitmap:
3440 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3442 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3443 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3444 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3448 * mono_compress_bitmap:
3449 * @dest: destination buffer
3450 * @bitmap: bitmap buffer
3451 * @size: size of @bitmap in bytes
3453 * This is a mono internal function.
3454 * The @bitmap data is compressed into a format that is small but
3455 * still searchable in few instructions by the JIT and runtime.
3456 * The compressed data is stored in the buffer pointed to by the
3457 * @dest array. Passing a #NULL value for @dest allows to just compute
3458 * the size of the buffer.
3459 * This compression algorithm assumes the bits set in the bitmap are
3460 * few and far between, like in interface bitmaps.
3461 * Returns: The size of the compressed bitmap in bytes.
3464 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3468 const uint8_t *end = bitmap + size;
3469 while (bitmap < end) {
3470 if (*bitmap || numz == 255) {
3494 * mono_class_interface_match:
3495 * @bitmap: a compressed bitmap buffer
3496 * @id: the index to check in the bitmap
3498 * This is a mono internal function.
3499 * Checks if a bit is set in a compressed interface bitmap. @id must
3500 * be already checked for being smaller than the maximum id encoded in the
3503 * Returns: A non-zero value if bit @id is set in the bitmap @bitmap,
3507 mono_class_interface_match (const uint8_t *bitmap, int id)
3510 id -= bitmap [0] * 8;
3514 return bitmap [1] & (1 << id);
3523 * Return -1 on failure and set klass->has_failure and store a MonoErrorBoxed with the details.
3524 * LOCKING: Acquires the loader lock.
3527 setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite)
3531 int i, j, max_iid, num_ifaces;
3532 MonoClass **interfaces_full = NULL;
3533 int *interface_offsets_full = NULL;
3535 GPtrArray **ifaces_array = NULL;
3536 int interface_offsets_count;
3537 MonoClass **array_interfaces = NULL;
3538 int num_array_interfaces;
3539 int is_enumerator = FALSE;
3541 mono_class_setup_supertypes (klass);
3543 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3544 * implicit interfaces have the property that they are assigned the same slot in the
3545 * vtables for compatible interfaces
3547 array_interfaces = get_implicit_generic_array_interfaces (klass, &num_array_interfaces, &is_enumerator);
3549 /* compute maximum number of slots and maximum interface id */
3551 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3552 ifaces_array = g_new0 (GPtrArray *, klass->idepth);
3553 for (j = 0; j < klass->idepth; j++) {
3554 k = klass->supertypes [j];
3555 num_ifaces += k->interface_count;
3556 for (i = 0; i < k->interface_count; i++) {
3557 ic = k->interfaces [i];
3559 mono_class_init (ic);
3561 if (max_iid < ic->interface_id)
3562 max_iid = ic->interface_id;
3564 ifaces = mono_class_get_implemented_interfaces (k, &error);
3565 if (!mono_error_ok (&error)) {
3566 char *name = mono_type_get_full_name (k);
3567 mono_class_set_type_load_failure (klass, "Error getting the interfaces of %s due to %s", name, mono_error_get_message (&error));
3569 mono_error_cleanup (&error);
3574 num_ifaces += ifaces->len;
3575 for (i = 0; i < ifaces->len; ++i) {
3576 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3577 if (max_iid < ic->interface_id)
3578 max_iid = ic->interface_id;
3580 ifaces_array [j] = ifaces;
3584 for (i = 0; i < num_array_interfaces; ++i) {
3585 ic = array_interfaces [i];
3586 mono_class_init (ic);
3587 if (max_iid < ic->interface_id)
3588 max_iid = ic->interface_id;
3591 if (MONO_CLASS_IS_INTERFACE (klass)) {
3593 if (max_iid < klass->interface_id)
3594 max_iid = klass->interface_id;
3597 /* compute vtable offset for interfaces */
3598 interfaces_full = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3599 interface_offsets_full = (int *)g_malloc (sizeof (int) * num_ifaces);
3601 for (i = 0; i < num_ifaces; i++)
3602 interface_offsets_full [i] = -1;
3604 /* skip the current class */
3605 for (j = 0; j < klass->idepth - 1; j++) {
3606 k = klass->supertypes [j];
3607 ifaces = ifaces_array [j];
3610 for (i = 0; i < ifaces->len; ++i) {
3612 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3614 /*Force the sharing of interface offsets between parent and subtypes.*/
3615 io = mono_class_interface_offset (k, ic);
3617 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3622 g_assert (klass == klass->supertypes [klass->idepth - 1]);
3623 ifaces = ifaces_array [klass->idepth - 1];
3625 for (i = 0; i < ifaces->len; ++i) {
3627 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3628 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3630 count = count_virtual_methods (ic);
3632 char *name = mono_type_get_full_name (ic);
3633 mono_class_set_type_load_failure (klass, "Error calculating interface offset of %s", name);
3642 if (MONO_CLASS_IS_INTERFACE (klass))
3643 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, klass, cur_slot, TRUE);
3645 if (num_array_interfaces) {
3646 if (is_enumerator) {
3647 int ienumerator_idx = find_array_interface (klass, "IEnumerator`1");
3648 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ienumerator_idx]);
3649 g_assert (ienumerator_offset >= 0);
3650 for (i = 0; i < num_array_interfaces; ++i) {
3651 ic = array_interfaces [i];
3652 if (strcmp (ic->name, "IEnumerator`1") == 0)
3653 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3655 g_assert_not_reached ();
3656 /*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);*/
3659 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3660 int ilist_iface_idx = find_array_interface (klass, "IList`1");
3661 MonoClass* ilist_class = klass->interfaces [ilist_iface_idx];
3662 int ireadonlylist_iface_idx = find_array_interface (klass, "IReadOnlyList`1");
3663 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? klass->interfaces [ireadonlylist_iface_idx] : NULL;
3664 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3665 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3666 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3667 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ilist_iface_idx]);
3668 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3669 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3670 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ireadonlylist_iface_idx]) : -1;
3671 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3672 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3673 for (i = 0; i < num_array_interfaces; ++i) {
3675 ic = array_interfaces [i];
3676 if (mono_class_get_generic_class (ic)->container_class == mono_defaults.generic_ilist_class)
3677 offset = ilist_offset;
3678 else if (strcmp (ic->name, "ICollection`1") == 0)
3679 offset = icollection_offset;
3680 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3681 offset = ienumerable_offset;
3682 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3683 offset = ireadonlylist_offset;
3684 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3685 offset = ireadonlycollection_offset;
3687 g_assert_not_reached ();
3688 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3689 /*g_print ("type %s has %s offset at %d (%s)\n", klass->name, ic->name, offset, klass->interfaces [0]->name);*/
3694 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3695 if (interface_offsets_full [i] != -1)
3696 interface_offsets_count ++;
3699 /* Publish the data */
3700 mono_loader_lock ();
3702 klass->max_interface_id = max_iid;
3704 * We might get called multiple times:
3705 * - mono_class_init ()
3706 * - mono_class_setup_vtable ().
3707 * - mono_class_setup_interface_offsets ().
3708 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3709 * means we have to overwrite those when called from other places (#4440).
3711 if (klass->interfaces_packed) {
3713 g_assert (klass->interface_offsets_count == interface_offsets_count);
3717 klass->interface_offsets_count = interface_offsets_count;
3718 klass->interfaces_packed = (MonoClass **)mono_class_alloc (klass, sizeof (MonoClass*) * interface_offsets_count);
3719 klass->interface_offsets_packed = (guint16 *)mono_class_alloc (klass, sizeof (guint16) * interface_offsets_count);
3720 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3721 #ifdef COMPRESSED_INTERFACE_BITMAP
3722 bitmap = g_malloc0 (bsize);
3724 bitmap = (uint8_t *)mono_class_alloc0 (klass, bsize);
3726 for (i = 0; i < interface_offsets_count; i++) {
3727 int id = interfaces_full [i]->interface_id;
3728 bitmap [id >> 3] |= (1 << (id & 7));
3729 klass->interfaces_packed [i] = interfaces_full [i];
3730 klass->interface_offsets_packed [i] = interface_offsets_full [i];
3731 /*if (num_array_interfaces)
3732 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]);*/
3734 #ifdef COMPRESSED_INTERFACE_BITMAP
3735 i = mono_compress_bitmap (NULL, bitmap, bsize);
3736 klass->interface_bitmap = mono_class_alloc0 (klass, i);
3737 mono_compress_bitmap (klass->interface_bitmap, bitmap, bsize);
3740 klass->interface_bitmap = bitmap;
3743 mono_loader_unlock ();
3746 g_free (interfaces_full);
3747 g_free (interface_offsets_full);
3748 g_free (array_interfaces);
3749 for (i = 0; i < klass->idepth; i++) {
3750 ifaces = ifaces_array [i];
3752 g_ptr_array_free (ifaces, TRUE);
3754 g_free (ifaces_array);
3756 //printf ("JUST DONE: ");
3757 //print_implemented_interfaces (klass);
3763 * Setup interface offsets for interfaces.
3765 * - klass->max_interface_id
3766 * - klass->interface_offsets_count
3767 * - klass->interfaces_packed
3768 * - klass->interface_offsets_packed
3769 * - klass->interface_bitmap
3771 * This function can fail @class.
3774 mono_class_setup_interface_offsets (MonoClass *klass)
3776 setup_interface_offsets (klass, 0, FALSE);
3779 /*Checks if @klass has @parent as one of it's parents type gtd
3783 * Bar<T> : Foo<Bar<Bar<T>>>
3787 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3789 klass = mono_class_get_generic_type_definition (klass);
3790 parent = mono_class_get_generic_type_definition (parent);
3791 mono_class_setup_supertypes (klass);
3792 mono_class_setup_supertypes (parent);
3794 return klass->idepth >= parent->idepth &&
3795 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3799 mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup)
3801 MonoGenericInst *ginst;
3804 if (!mono_class_is_ginst (klass)) {
3805 mono_class_setup_vtable_full (klass, in_setup);
3806 return !mono_class_has_failure (klass);
3809 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup);
3810 if (mono_class_set_type_load_failure_causedby_class (klass, mono_class_get_generic_class (klass)->container_class, "Failed to load generic definition vtable"))
3813 ginst = mono_class_get_generic_class (klass)->context.class_inst;
3814 for (i = 0; i < ginst->type_argc; ++i) {
3816 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3818 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3819 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3820 if (mono_class_has_gtd_parent (klass, arg) || mono_class_has_gtd_parent (arg, klass))
3822 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3823 mono_class_set_type_load_failure (klass, "Failed to load generic parameter %d", i);
3831 * mono_class_setup_vtable:
3833 * Creates the generic vtable of CLASS.
3834 * Initializes the following fields in MonoClass:
3837 * Plus all the fields initialized by setup_interface_offsets ().
3838 * If there is an error during vtable construction, klass->has_failure
3839 * is set and details are stored in a MonoErrorBoxed.
3841 * LOCKING: Acquires the loader lock.
3844 mono_class_setup_vtable (MonoClass *klass)
3846 mono_class_setup_vtable_full (klass, NULL);
3850 mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
3853 MonoMethod **overrides;
3854 MonoGenericContext *context;
3862 if (MONO_CLASS_IS_INTERFACE (klass)) {
3863 /* This sets method->slot for all methods if this is an interface */
3864 mono_class_setup_methods (klass);
3868 if (mono_class_has_failure (klass))
3871 if (g_list_find (in_setup, klass))
3874 mono_loader_lock ();
3876 if (klass->vtable) {
3877 mono_loader_unlock ();
3881 mono_stats.generic_vtable_count ++;
3882 in_setup = g_list_prepend (in_setup, klass);
3884 if (mono_class_is_ginst (klass)) {
3885 if (!mono_class_check_vtable_constraints (klass, in_setup)) {
3886 mono_loader_unlock ();
3887 g_list_remove (in_setup, klass);
3891 context = mono_class_get_context (klass);
3892 type_token = mono_class_get_generic_class (klass)->container_class->type_token;
3894 context = (MonoGenericContext *) mono_class_try_get_generic_container (klass); //FIXME is this a case of a try?
3895 type_token = klass->type_token;
3898 if (image_is_dynamic (klass->image)) {
3899 /* Generic instances can have zero method overrides without causing any harm.
3900 * This is true since we don't do layout all over again for them, we simply inflate
3901 * the layout of the parent.
3903 mono_reflection_get_dynamic_overrides (klass, &overrides, &onum, &error);
3904 if (!is_ok (&error)) {
3905 mono_loader_unlock ();
3906 g_list_remove (in_setup, klass);
3907 mono_class_set_type_load_failure (klass, "Could not load list of method overrides due to %s", mono_error_get_message (&error));
3908 mono_error_cleanup (&error);
3912 /* The following call fails if there are missing methods in the type */
3913 /* FIXME it's probably a good idea to avoid this for generic instances. */
3914 ok = mono_class_get_overrides_full (klass->image, type_token, &overrides, &onum, context);
3918 mono_class_setup_vtable_general (klass, overrides, onum, in_setup);
3920 mono_class_set_type_load_failure (klass, "Could not load list of method overrides");
3924 mono_loader_unlock ();
3925 g_list_remove (in_setup, klass);
3930 #define DEBUG_INTERFACE_VTABLE_CODE 0
3931 #define TRACE_INTERFACE_VTABLE_CODE 0
3932 #define VERIFY_INTERFACE_VTABLE_CODE 0
3933 #define VTABLE_SELECTOR (1)
3935 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3936 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3937 if (!(VTABLE_SELECTOR)) break; \
3941 #define DEBUG_INTERFACE_VTABLE(stmt)
3944 #if TRACE_INTERFACE_VTABLE_CODE
3945 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3946 if (!(VTABLE_SELECTOR)) break; \
3950 #define TRACE_INTERFACE_VTABLE(stmt)
3953 #if VERIFY_INTERFACE_VTABLE_CODE
3954 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3955 if (!(VTABLE_SELECTOR)) break; \
3959 #define VERIFY_INTERFACE_VTABLE(stmt)
3963 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3965 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3969 GString *res = g_string_new ("");
3971 g_string_append_c (res, '(');
3972 for (i = 0; i < sig->param_count; ++i) {
3974 g_string_append_c (res, ',');
3975 mono_type_get_desc (res, sig->params [i], include_namespace);
3977 g_string_append (res, ")=>");
3978 if (sig->ret != NULL) {
3979 mono_type_get_desc (res, sig->ret, include_namespace);
3981 g_string_append (res, "NULL");
3984 g_string_free (res, FALSE);
3988 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3989 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3990 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3991 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3999 is_wcf_hack_disabled (void)
4001 static gboolean disabled;
4002 static gboolean inited = FALSE;
4004 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
4011 check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
4013 MonoMethodSignature *cmsig, *imsig;
4014 if (strcmp (im->name, cm->name) == 0) {
4015 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
4016 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
4019 if (! slot_is_empty) {
4020 if (require_newslot) {
4021 if (! interface_is_explicitly_implemented_by_class) {
4022 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
4025 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4026 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
4030 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
4033 cmsig = mono_method_signature (cm);
4034 imsig = mono_method_signature (im);
4035 if (!cmsig || !imsig) {
4036 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
4040 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4041 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
4042 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4043 TRACE_INTERFACE_VTABLE (printf ("]"));
4046 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
4047 if (mono_security_core_clr_enabled ())
4048 mono_security_core_clr_check_override (klass, cm, im);
4050 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
4051 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4052 char *body_name = mono_method_full_name (cm, TRUE);
4053 char *decl_name = mono_method_full_name (im, TRUE);
4054 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4062 MonoClass *ic = im->klass;
4063 const char *ic_name_space = ic->name_space;
4064 const char *ic_name = ic->name;
4067 if (! require_newslot) {
4068 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
4071 if (cm->klass->rank == 0) {
4072 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
4075 cmsig = mono_method_signature (cm);
4076 imsig = mono_method_signature (im);
4077 if (!cmsig || !imsig) {
4078 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
4082 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4083 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
4084 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4085 TRACE_INTERFACE_VTABLE (printf ("]"));
4088 if (mono_class_get_image (ic) != mono_defaults.corlib) {
4089 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
4092 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
4093 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
4096 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))) {
4097 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
4101 subname = strstr (cm->name, ic_name_space);
4102 if (subname != cm->name) {
4103 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
4106 subname += strlen (ic_name_space);
4107 if (subname [0] != '.') {
4108 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
4112 if (strstr (subname, ic_name) != subname) {
4113 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
4116 subname += strlen (ic_name);
4117 if (subname [0] != '.') {
4118 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
4122 if (strcmp (subname, im->name) != 0) {
4123 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
4127 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
4128 if (mono_security_core_clr_enabled ())
4129 mono_security_core_clr_check_override (klass, cm, im);
4131 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
4132 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4133 char *body_name = mono_method_full_name (cm, TRUE);
4134 char *decl_name = mono_method_full_name (im, TRUE);
4135 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4145 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
4147 foreach_override (gpointer key, gpointer value, gpointer user_data) {
4148 MonoMethod *method = key;
4149 MonoMethod *override = value;
4150 MonoClass *method_class = mono_method_get_class (method);
4151 MonoClass *override_class = mono_method_get_class (override);
4153 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
4154 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
4155 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
4158 print_overrides (GHashTable *override_map, const char *message) {
4160 printf ("Override map \"%s\" START:\n", message);
4161 g_hash_table_foreach (override_map, foreach_override, NULL);
4162 printf ("Override map \"%s\" END.\n", message);
4164 printf ("Override map \"%s\" EMPTY.\n", message);
4168 print_vtable_full (MonoClass *klass, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
4169 char *full_name = mono_type_full_name (&klass->byval_arg);
4173 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
4175 if (print_interfaces) {
4176 print_implemented_interfaces (klass);
4177 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
4180 if (klass->parent) {
4181 parent_size = klass->parent->vtable_size;
4185 for (i = 0; i < size; ++i) {
4186 MonoMethod *cm = vtable [i];
4187 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
4188 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
4190 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
4198 #if VERIFY_INTERFACE_VTABLE_CODE
4200 mono_method_try_get_vtable_index (MonoMethod *method)
4202 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4203 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4204 if (imethod->declaring->is_generic)
4205 return imethod->declaring->slot;
4207 return method->slot;
4211 mono_class_verify_vtable (MonoClass *klass)
4214 char *full_name = mono_type_full_name (&klass->byval_arg);
4216 printf ("*** Verifying VTable of class '%s' \n", full_name);
4220 if (!klass->methods)
4223 for (i = 0; i < klass->method.count; ++i) {
4224 MonoMethod *cm = klass->methods [i];
4227 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4231 full_name = mono_method_full_name (cm, TRUE);
4233 slot = mono_method_try_get_vtable_index (cm);
4235 if (slot >= klass->vtable_size) {
4236 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, klass->vtable_size);
4240 if (slot >= 0 && klass->vtable [slot] != cm && (klass->vtable [slot])) {
4241 char *other_name = klass->vtable [slot] ? mono_method_full_name (klass->vtable [slot], TRUE) : g_strdup ("[null value]");
4242 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4243 g_free (other_name);
4246 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4253 print_unimplemented_interface_method_info (MonoClass *klass, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4255 char *method_signature;
4258 for (index = 0; index < onum; ++index) {
4259 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4260 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4262 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4263 type_name = mono_type_full_name (&klass->byval_arg);
4264 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4265 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4266 g_free (method_signature);
4268 mono_class_setup_methods (klass);
4269 if (mono_class_has_failure (klass)) {
4270 char *name = mono_type_get_full_name (klass);
4271 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4275 for (index = 0; index < klass->method.count; ++index) {
4276 MonoMethod *cm = klass->methods [index];
4277 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4279 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4280 g_free (method_signature);
4285 mono_method_get_method_definition (MonoMethod *method)
4287 while (method->is_inflated)
4288 method = ((MonoMethodInflated*)method)->declaring;
4293 verify_class_overrides (MonoClass *klass, MonoMethod **overrides, int onum)
4297 for (i = 0; i < onum; ++i) {
4298 MonoMethod *decl = overrides [i * 2];
4299 MonoMethod *body = overrides [i * 2 + 1];
4301 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (klass)) {
4302 mono_class_set_type_load_failure (klass, "Method belongs to a different class than the declared one");
4306 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4307 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4308 mono_class_set_type_load_failure (klass, "Method must not be static to override a base type");
4310 mono_class_set_type_load_failure (klass, "Method must be virtual to override a base type");
4314 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4315 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4316 mono_class_set_type_load_failure (klass, "Cannot override a static method in a base type");
4318 mono_class_set_type_load_failure (klass, "Cannot override a non virtual method in a base type");
4322 if (!mono_class_is_assignable_from_slow (decl->klass, klass)) {
4323 mono_class_set_type_load_failure (klass, "Method overrides a class or interface that is not extended or implemented by this type");
4327 body = mono_method_get_method_definition (body);
4328 decl = mono_method_get_method_definition (decl);
4330 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4331 char *body_name = mono_method_full_name (body, TRUE);
4332 char *decl_name = mono_method_full_name (decl, TRUE);
4333 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4343 mono_class_need_stelemref_method (MonoClass *klass)
4345 return klass->rank == 1 && MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg);
4349 * LOCKING: this is supposed to be called with the loader lock held.
4352 mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int onum, GList *in_setup)
4356 MonoMethod **vtable;
4357 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4358 GPtrArray *ifaces = NULL;
4359 GHashTable *override_map = NULL;
4361 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4362 int first_non_interface_slot;
4364 GSList *virt_methods = NULL, *l;
4365 int stelemref_slot = 0;
4370 if (overrides && !verify_class_overrides (klass, overrides, onum))
4373 ifaces = mono_class_get_implemented_interfaces (klass, &error);
4374 if (!mono_error_ok (&error)) {
4375 char *name = mono_type_get_full_name (klass);
4376 mono_class_set_type_load_failure (klass, "Could not resolve %s interfaces due to %s", name, mono_error_get_message (&error));
4378 mono_error_cleanup (&error);
4380 } else if (ifaces) {
4381 for (i = 0; i < ifaces->len; i++) {
4382 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
4383 max_vtsize += ic->method.count;
4385 g_ptr_array_free (ifaces, TRUE);
4389 if (klass->parent) {
4390 mono_class_init (klass->parent);
4391 mono_class_setup_vtable_full (klass->parent, in_setup);
4393 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class failed to load"))
4396 max_vtsize += klass->parent->vtable_size;
4397 cur_slot = klass->parent->vtable_size;
4400 max_vtsize += klass->method.count;
4402 /*Array have a slot for stelemref*/
4403 if (mono_class_need_stelemref_method (klass)) {
4404 stelemref_slot = cur_slot;
4409 vtable = (MonoMethod **)alloca (sizeof (gpointer) * max_vtsize);
4410 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4412 /* printf ("METAINIT %s.%s\n", klass->name_space, klass->name); */
4414 cur_slot = setup_interface_offsets (klass, cur_slot, TRUE);
4415 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4418 max_iid = klass->max_interface_id;
4419 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4421 /* Optimized version for generic instances */
4422 if (mono_class_is_ginst (klass)) {
4424 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4427 mono_class_setup_vtable_full (gklass, in_setup);
4428 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Could not load generic definition"))
4431 tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * gklass->vtable_size);
4432 klass->vtable_size = gklass->vtable_size;
4433 for (i = 0; i < gklass->vtable_size; ++i)
4434 if (gklass->vtable [i]) {
4435 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], klass, mono_class_get_context (klass), &error);
4436 if (!mono_error_ok (&error)) {
4437 mono_class_set_type_load_failure (klass, "Could not inflate method due to %s", mono_error_get_message (&error));
4438 mono_error_cleanup (&error);
4442 tmp [i]->slot = gklass->vtable [i]->slot;
4444 mono_memory_barrier ();
4445 klass->vtable = tmp;
4447 /* Have to set method->slot for abstract virtual methods */
4448 if (klass->methods && gklass->methods) {
4449 for (i = 0; i < klass->method.count; ++i)
4450 if (klass->methods [i]->slot == -1)
4451 klass->methods [i]->slot = gklass->methods [i]->slot;
4457 if (klass->parent && klass->parent->vtable_size) {
4458 MonoClass *parent = klass->parent;
4461 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4463 // Also inherit parent interface vtables, just as a starting point.
4464 // This is needed otherwise bug-77127.exe fails when the property methods
4465 // have different names in the iterface and the class, because for child
4466 // classes the ".override" information is not used anymore.
4467 for (i = 0; i < parent->interface_offsets_count; i++) {
4468 MonoClass *parent_interface = parent->interfaces_packed [i];
4469 int interface_offset = mono_class_interface_offset (klass, parent_interface);
4470 /*FIXME this is now dead code as this condition will never hold true.
4471 Since interface offsets are inherited then the offset of an interface implemented
4472 by a parent will never be the out of it's vtable boundary.
4474 if (interface_offset >= parent->vtable_size) {
4475 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4478 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4479 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4480 for (j = 0; j < parent_interface->method.count && !mono_class_has_failure (klass); j++) {
4481 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4482 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4483 parent_interface_offset + j, parent_interface_offset, j,
4484 interface_offset + j, interface_offset, j));
4491 /*Array have a slot for stelemref*/
4492 if (mono_class_need_stelemref_method (klass)) {
4493 MonoMethod *method = mono_marshal_get_virtual_stelemref (klass);
4495 method->slot = stelemref_slot;
4497 g_assert (method->slot == stelemref_slot);
4499 vtable [stelemref_slot] = method;
4502 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4503 /* override interface methods */
4504 for (i = 0; i < onum; i++) {
4505 MonoMethod *decl = overrides [i*2];
4506 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4508 dslot = mono_method_get_vtable_slot (decl);
4510 mono_class_set_type_load_failure (klass, "");
4514 dslot += mono_class_interface_offset (klass, decl->klass);
4515 vtable [dslot] = overrides [i*2 + 1];
4516 vtable [dslot]->slot = dslot;
4518 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4520 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4522 if (mono_security_core_clr_enabled ())
4523 mono_security_core_clr_check_override (klass, vtable [dslot], decl);
4526 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4527 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4530 * Create a list of virtual methods to avoid calling
4531 * mono_class_get_virtual_methods () which is slow because of the metadata
4535 gpointer iter = NULL;
4538 virt_methods = NULL;
4539 while ((cm = mono_class_get_virtual_methods (klass, &iter))) {
4540 virt_methods = g_slist_prepend (virt_methods, cm);
4542 if (mono_class_has_failure (klass))
4546 // Loop on all implemented interfaces...
4547 for (i = 0; i < klass->interface_offsets_count; i++) {
4548 MonoClass *parent = klass->parent;
4550 gboolean interface_is_explicitly_implemented_by_class;
4553 ic = klass->interfaces_packed [i];
4554 ic_offset = mono_class_interface_offset (klass, ic);
4556 mono_class_setup_methods (ic);
4557 if (mono_class_has_failure (ic))
4560 // Check if this interface is explicitly implemented (instead of just inherited)
4561 if (parent != NULL) {
4562 int implemented_interfaces_index;
4563 interface_is_explicitly_implemented_by_class = FALSE;
4564 for (implemented_interfaces_index = 0; implemented_interfaces_index < klass->interface_count; implemented_interfaces_index++) {
4565 if (ic == klass->interfaces [implemented_interfaces_index]) {
4566 interface_is_explicitly_implemented_by_class = TRUE;
4571 interface_is_explicitly_implemented_by_class = TRUE;
4574 // Loop on all interface methods...
4575 for (im_index = 0; im_index < ic->method.count; im_index++) {
4576 MonoMethod *im = ic->methods [im_index];
4577 int im_slot = ic_offset + im->slot;
4578 MonoMethod *override_im = (override_map != NULL) ? (MonoMethod *)g_hash_table_lookup (override_map, im) : NULL;
4580 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4583 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4585 // If there is an explicit implementation, just use it right away,
4586 // otherwise look for a matching method
4587 if (override_im == NULL) {
4591 // First look for a suitable method among the class methods
4592 for (l = virt_methods; l; l = l->next) {
4593 cm = (MonoMethod *)l->data;
4594 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)));
4595 if (check_interface_method_override (klass, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
4596 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4597 vtable [im_slot] = cm;
4598 /* Why do we need this? */
4603 TRACE_INTERFACE_VTABLE (printf ("\n"));
4604 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4608 // If the slot is still empty, look in all the inherited virtual methods...
4609 if ((vtable [im_slot] == NULL) && klass->parent != NULL) {
4610 MonoClass *parent = klass->parent;
4611 // Reverse order, so that last added methods are preferred
4612 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4613 MonoMethod *cm = parent->vtable [cm_index];
4615 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));
4616 if ((cm != NULL) && check_interface_method_override (klass, im, cm, FALSE, FALSE, TRUE)) {
4617 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4618 vtable [im_slot] = cm;
4619 /* Why do we need this? */
4625 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4627 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4631 g_assert (vtable [im_slot] == override_im);
4636 // If the class is not abstract, check that all its interface slots are full.
4637 // The check is done here and not directly at the end of the loop above because
4638 // it can happen (for injected generic array interfaces) that the same slot is
4639 // processed multiple times (those interfaces have overlapping slots), and it
4640 // will not always be the first pass the one that fills the slot.
4641 if (!mono_class_is_abstract (klass)) {
4642 for (i = 0; i < klass->interface_offsets_count; i++) {
4646 ic = klass->interfaces_packed [i];
4647 ic_offset = mono_class_interface_offset (klass, ic);
4649 for (im_index = 0; im_index < ic->method.count; im_index++) {
4650 MonoMethod *im = ic->methods [im_index];
4651 int im_slot = ic_offset + im->slot;
4653 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4656 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4657 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4658 if (vtable [im_slot] == NULL) {
4659 print_unimplemented_interface_method_info (klass, ic, im, im_slot, overrides, onum);
4666 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4667 for (l = virt_methods; l; l = l->next) {
4668 cm = (MonoMethod *)l->data;
4670 * If the method is REUSE_SLOT, we must check in the
4671 * base class for a method to override.
4673 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4675 for (k = klass->parent; k ; k = k->parent) {
4680 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4681 MonoMethodSignature *cmsig, *m1sig;
4683 cmsig = mono_method_signature (cm);
4684 m1sig = mono_method_signature (m1);
4686 if (!cmsig || !m1sig) {
4687 /* FIXME proper error message */
4688 mono_class_set_type_load_failure (klass, "");
4692 if (!strcmp(cm->name, m1->name) &&
4693 mono_metadata_signature_equal (cmsig, m1sig)) {
4695 if (mono_security_core_clr_enabled ())
4696 mono_security_core_clr_check_override (klass, cm, m1);
4698 slot = mono_method_get_vtable_slot (m1);
4702 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4703 char *body_name = mono_method_full_name (cm, TRUE);
4704 char *decl_name = mono_method_full_name (m1, TRUE);
4705 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4711 g_assert (cm->slot < max_vtsize);
4713 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4714 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4715 mono_method_full_name (m1, 1), m1,
4716 mono_method_full_name (cm, 1), cm));
4717 g_hash_table_insert (override_map, m1, cm);
4721 if (mono_class_has_failure (k))
4731 /*Non final newslot methods must be given a non-interface vtable slot*/
4732 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4736 cm->slot = cur_slot++;
4738 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4739 vtable [cm->slot] = cm;
4742 /* override non interface methods */
4743 for (i = 0; i < onum; i++) {
4744 MonoMethod *decl = overrides [i*2];
4745 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4746 g_assert (decl->slot != -1);
4747 vtable [decl->slot] = overrides [i*2 + 1];
4748 overrides [i * 2 + 1]->slot = decl->slot;
4750 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4751 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4752 mono_method_full_name (decl, 1), decl,
4753 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4754 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4756 if (mono_security_core_clr_enabled ())
4757 mono_security_core_clr_check_override (klass, vtable [decl->slot], decl);
4762 * If a method occupies more than one place in the vtable, and it is
4763 * overriden, then change the other occurances too.
4768 for (i = 0; i < max_vtsize; ++i)
4770 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4772 cm = (MonoMethod *)g_hash_table_lookup (override_map, vtable [i]);
4777 g_hash_table_destroy (override_map);
4778 override_map = NULL;
4781 g_slist_free (virt_methods);
4782 virt_methods = NULL;
4784 /* Ensure that all vtable slots are filled with concrete instance methods */
4785 if (!mono_class_is_abstract (klass)) {
4786 for (i = 0; i < cur_slot; ++i) {
4787 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4788 char *type_name = mono_type_get_full_name (klass);
4789 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4790 mono_class_set_type_load_failure (klass, "Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name);
4792 g_free (method_name);
4798 if (mono_class_is_ginst (klass)) {
4799 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4801 mono_class_init (gklass);
4803 klass->vtable_size = MAX (gklass->vtable_size, cur_slot);
4805 /* Check that the vtable_size value computed in mono_class_init () is correct */
4806 if (klass->vtable_size)
4807 g_assert (cur_slot == klass->vtable_size);
4808 klass->vtable_size = cur_slot;
4811 /* Try to share the vtable with our parent. */
4812 if (klass->parent && (klass->parent->vtable_size == klass->vtable_size) && (memcmp (klass->parent->vtable, vtable, sizeof (gpointer) * klass->vtable_size) == 0)) {
4813 mono_memory_barrier ();
4814 klass->vtable = klass->parent->vtable;
4816 MonoMethod **tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * klass->vtable_size);
4817 memcpy (tmp, vtable, sizeof (gpointer) * klass->vtable_size);
4818 mono_memory_barrier ();
4819 klass->vtable = tmp;
4822 DEBUG_INTERFACE_VTABLE (print_vtable_full (klass, klass->vtable, klass->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4823 if (mono_print_vtable) {
4826 print_implemented_interfaces (klass);
4828 for (i = 0; i <= max_iid; i++)
4829 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
4832 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&klass->byval_arg),
4833 klass->vtable_size, icount);
4835 for (i = 0; i < cur_slot; ++i) {
4840 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4841 mono_method_full_name (cm, TRUE));
4847 printf ("Interfaces %s.%s (max_iid = %d)\n", klass->name_space,
4848 klass->name, max_iid);
4850 for (i = 0; i < klass->interface_count; i++) {
4851 ic = klass->interfaces [i];
4852 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4853 mono_class_interface_offset (klass, ic),
4854 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4857 for (k = klass->parent; k ; k = k->parent) {
4858 for (i = 0; i < k->interface_count; i++) {
4859 ic = k->interfaces [i];
4860 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4861 mono_class_interface_offset (klass, ic),
4862 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4868 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (klass));
4873 char *name = mono_type_get_full_name (klass);
4874 mono_class_set_type_load_failure (klass, "VTable setup of type %s failed", name);
4877 g_hash_table_destroy (override_map);
4879 g_slist_free (virt_methods);
4884 * mono_method_get_vtable_slot:
4886 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4887 * LOCKING: Acquires the loader lock.
4889 * FIXME Use proper MonoError machinery here.
4892 mono_method_get_vtable_slot (MonoMethod *method)
4894 if (method->slot == -1) {
4895 mono_class_setup_vtable (method->klass);
4896 if (mono_class_has_failure (method->klass))
4898 if (method->slot == -1) {
4902 if (!mono_class_is_ginst (method->klass)) {
4903 g_assert (method->is_inflated);
4904 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4907 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4908 g_assert (mono_class_is_ginst (method->klass));
4909 gklass = mono_class_get_generic_class (method->klass)->container_class;
4910 mono_class_setup_methods (method->klass);
4911 g_assert (method->klass->methods);
4912 for (i = 0; i < method->klass->method.count; ++i) {
4913 if (method->klass->methods [i] == method)
4916 g_assert (i < method->klass->method.count);
4917 g_assert (gklass->methods);
4918 method->slot = gklass->methods [i]->slot;
4920 g_assert (method->slot != -1);
4922 return method->slot;
4926 * mono_method_get_vtable_index:
4929 * Returns the index into the runtime vtable to access the method or,
4930 * in the case of a virtual generic method, the virtual generic method
4931 * thunk. Returns -1 on failure.
4933 * FIXME Use proper MonoError machinery here.
4936 mono_method_get_vtable_index (MonoMethod *method)
4938 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4939 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4940 if (imethod->declaring->is_generic)
4941 return mono_method_get_vtable_slot (imethod->declaring);
4943 return mono_method_get_vtable_slot (method);
4946 static MonoMethod *default_ghc = NULL;
4947 static MonoMethod *default_finalize = NULL;
4948 static int finalize_slot = -1;
4949 static int ghc_slot = -1;
4952 initialize_object_slots (MonoClass *klass)
4957 if (klass == mono_defaults.object_class) {
4958 mono_class_setup_vtable (klass);
4959 for (i = 0; i < klass->vtable_size; ++i) {
4960 MonoMethod *cm = klass->vtable [i];
4962 if (!strcmp (cm->name, "GetHashCode"))
4964 else if (!strcmp (cm->name, "Finalize"))
4968 g_assert (ghc_slot > 0);
4969 default_ghc = klass->vtable [ghc_slot];
4971 g_assert (finalize_slot > 0);
4972 default_finalize = klass->vtable [finalize_slot];
4977 MonoMethod *array_method;
4979 } GenericArrayMethodInfo;
4981 static int generic_array_method_num = 0;
4982 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4985 generic_array_methods (MonoClass *klass)
4987 int i, count_generic = 0;
4988 GList *list = NULL, *tmp;
4989 if (generic_array_method_num)
4990 return generic_array_method_num;
4991 mono_class_setup_methods (klass->parent); /*This is setting up System.Array*/
4992 g_assert (!mono_class_has_failure (klass->parent)); /*So hitting this assert is a huge problem*/
4993 for (i = 0; i < klass->parent->method.count; i++) {
4994 MonoMethod *m = klass->parent->methods [i];
4995 if (!strncmp (m->name, "InternalArray__", 15)) {
4997 list = g_list_prepend (list, m);
5000 list = g_list_reverse (list);
5001 generic_array_method_info = (GenericArrayMethodInfo *)mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
5003 for (tmp = list; tmp; tmp = tmp->next) {
5004 const char *mname, *iname;
5006 MonoMethod *m = (MonoMethod *)tmp->data;
5007 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
5008 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
5010 generic_array_method_info [i].array_method = m;
5011 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
5012 iname = "System.Collections.Generic.ICollection`1.";
5013 mname = m->name + 27;
5014 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
5015 iname = "System.Collections.Generic.IEnumerable`1.";
5016 mname = m->name + 27;
5017 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
5018 iname = "System.Collections.Generic.IReadOnlyList`1.";
5019 mname = m->name + strlen (ireadonlylist_prefix);
5020 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
5021 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
5022 mname = m->name + strlen (ireadonlycollection_prefix);
5023 } else if (!strncmp (m->name, "InternalArray__", 15)) {
5024 iname = "System.Collections.Generic.IList`1.";
5025 mname = m->name + 15;
5027 g_assert_not_reached ();
5030 name = (gchar *)mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
5031 strcpy (name, iname);
5032 strcpy (name + strlen (iname), mname);
5033 generic_array_method_info [i].name = name;
5036 /*g_print ("array generic methods: %d\n", count_generic);*/
5038 generic_array_method_num = count_generic;
5040 return generic_array_method_num;
5044 setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos)
5046 MonoGenericContext tmp_context;
5049 tmp_context.class_inst = NULL;
5050 tmp_context.method_inst = mono_class_get_generic_class (iface)->context.class_inst;
5051 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
5053 for (i = 0; i < generic_array_method_num; i++) {
5055 MonoMethod *m = generic_array_method_info [i].array_method;
5056 MonoMethod *inflated;
5058 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
5059 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
5060 methods [pos++] = mono_marshal_get_generic_array_helper (klass, iface, generic_array_method_info [i].name, inflated);
5065 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
5067 int null_length = strlen ("(null)");
5068 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
5069 char *s = (char *)mono_image_alloc (image, len);
5072 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
5073 g_assert (result == len - 1);
5080 * @klass: the class to initialize
5082 * Compute the instance_size, class_size and other infos that cannot be
5083 * computed at mono_class_get() time. Also compute vtable_size if possible.
5084 * Returns TRUE on success or FALSE if there was a problem in loading
5085 * the type (incorrect assemblies, missing assemblies, methods, etc).
5086 * Initializes the following fields in @klass:
5087 * - all the fields initialized by mono_class_init_sizes ()
5092 * LOCKING: Acquires the loader lock.
5095 mono_class_init (MonoClass *klass)
5097 int i, vtable_size = 0, array_method_count = 0;
5098 MonoCachedClassInfo cached_info;
5099 gboolean has_cached_info;
5100 gboolean locked = FALSE;
5101 gboolean ghcimpl = FALSE;
5102 gboolean has_cctor = FALSE;
5103 int first_iface_slot = 0;
5107 /* Double-checking locking pattern */
5108 if (klass->inited || mono_class_has_failure (klass))
5109 return !mono_class_has_failure (klass);
5111 /*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/
5114 * This function can recursively call itself.
5116 GSList *init_list = (GSList *)mono_native_tls_get_value (init_pending_tls_id);
5117 if (g_slist_find (init_list, klass)) {
5118 mono_class_set_type_load_failure (klass, "Recursive type definition detected");
5121 init_list = g_slist_prepend (init_list, klass);
5122 mono_native_tls_set_value (init_pending_tls_id, init_list);
5125 * We want to avoid doing complicated work inside locks, so we compute all the required
5126 * information and write it to @klass inside a lock.
5129 if (mono_verifier_is_enabled_for_class (klass) && !mono_verifier_verify_class (klass)) {
5130 mono_class_set_type_load_failure (klass, "%s", concat_two_strings_with_zero (klass->image, klass->name, klass->image->assembly_name));
5134 if (klass->byval_arg.type == MONO_TYPE_ARRAY || klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5135 MonoClass *element_class = klass->element_class;
5136 if (!element_class->inited)
5137 mono_class_init (element_class);
5138 if (mono_class_set_type_load_failure_causedby_class (klass, element_class, "Could not load array element class"))
5142 mono_stats.initialized_class_count++;
5144 if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic) {
5145 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5147 mono_class_init (gklass);
5148 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic Type Definition failed to init"))
5151 mono_class_setup_interface_id (klass);
5154 if (klass->parent && !klass->parent->inited)
5155 mono_class_init (klass->parent);
5157 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
5159 /* Compute instance size etc. */
5160 init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
5161 if (mono_class_has_failure (klass))
5164 mono_class_setup_supertypes (klass);
5167 initialize_object_slots (klass);
5170 * Initialize the rest of the data without creating a generic vtable if possible.
5171 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5172 * also avoid computing a generic vtable.
5174 if (has_cached_info) {
5176 vtable_size = cached_info.vtable_size;
5177 ghcimpl = cached_info.ghcimpl;
5178 has_cctor = cached_info.has_cctor;
5179 } else if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5180 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5181 * The first slot if for array with.
5183 static int szarray_vtable_size[2] = { 0 };
5185 int slot = MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg) ? 0 : 1;
5188 if (!szarray_vtable_size [slot]) {
5189 mono_class_setup_vtable (klass);
5190 szarray_vtable_size [slot] = klass->vtable_size;
5191 vtable_size = klass->vtable_size;
5193 vtable_size = szarray_vtable_size[slot];
5195 } else if (mono_class_is_ginst (klass) && !MONO_CLASS_IS_INTERFACE (klass)) {
5196 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5198 /* Generic instance case */
5199 ghcimpl = gklass->ghcimpl;
5200 has_cctor = gklass->has_cctor;
5202 mono_class_setup_vtable (gklass);
5203 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to init"))
5206 vtable_size = gklass->vtable_size;
5210 /* ghcimpl is not currently used
5212 if (klass->parent) {
5213 MonoMethod *cmethod = klass->vtable [ghc_slot];
5214 if (cmethod->is_inflated)
5215 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5216 if (cmethod == default_ghc) {
5222 /* C# doesn't allow interfaces to have cctors */
5223 if (!MONO_CLASS_IS_INTERFACE (klass) || klass->image != mono_defaults.corlib) {
5224 MonoMethod *cmethod = NULL;
5226 if (mono_class_is_ginst (klass)) {
5227 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5229 /* Generic instance case */
5230 ghcimpl = gklass->ghcimpl;
5231 has_cctor = gklass->has_cctor;
5232 } else if (klass->type_token && !image_is_dynamic(klass->image)) {
5233 cmethod = find_method_in_metadata (klass, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5234 /* The find_method function ignores the 'flags' argument */
5235 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5238 mono_class_setup_methods (klass);
5239 if (mono_class_has_failure (klass))
5242 for (i = 0; i < klass->method.count; ++i) {
5243 MonoMethod *method = klass->methods [i];
5244 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5245 (strcmp (".cctor", method->name) == 0)) {
5255 array_method_count = 3 + (klass->rank > 1? 2: 1);
5257 if (klass->interface_count) {
5258 int count_generic = generic_array_methods (klass);
5259 array_method_count += klass->interface_count * count_generic;
5263 if (klass->parent) {
5264 if (!klass->parent->vtable_size)
5265 mono_class_setup_vtable (klass->parent);
5266 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class vtable failed to initialize"))
5268 g_assert (klass->parent->vtable_size);
5269 first_iface_slot = klass->parent->vtable_size;
5270 if (mono_class_need_stelemref_method (klass))
5275 * Do the actual changes to @klass inside the loader lock
5277 mono_loader_lock ();
5280 if (klass->inited || mono_class_has_failure (klass)) {
5281 mono_loader_unlock ();
5282 /* Somebody might have gotten in before us */
5283 return !mono_class_has_failure (klass);
5286 mono_stats.initialized_class_count++;
5288 if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic) {
5289 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5291 mono_stats.generic_class_count++;
5293 klass->method = gklass->method;
5294 klass->field = gklass->field;
5297 if (mono_class_is_ginst (klass) || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
5298 klass->nested_classes_inited = TRUE;
5299 klass->ghcimpl = ghcimpl;
5300 klass->has_cctor = has_cctor;
5302 klass->vtable_size = vtable_size;
5303 if (has_cached_info) {
5304 klass->has_finalize = cached_info.has_finalize;
5305 klass->has_finalize_inited = TRUE;
5308 klass->method.count = array_method_count;
5310 mono_loader_unlock ();
5313 setup_interface_offsets (klass, first_iface_slot, TRUE);
5315 if (mono_security_core_clr_enabled ())
5316 mono_security_core_clr_check_inheritance (klass);
5318 if (mono_class_is_ginst (klass) && !mono_verifier_class_is_valid_generic_instantiation (klass))
5319 mono_class_set_type_load_failure (klass, "Invalid generic instantiation");
5324 init_list = g_slist_remove (init_list, klass);
5325 mono_native_tls_set_value (init_pending_tls_id, init_list);
5327 /* Because of the double-checking locking pattern */
5328 mono_memory_barrier ();
5332 mono_loader_unlock ();
5334 return !mono_class_has_failure (klass);
5338 * mono_class_has_finalizer:
5340 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5344 mono_class_has_finalizer (MonoClass *klass)
5346 gboolean has_finalize = FALSE;
5348 if (klass->has_finalize_inited)
5349 return klass->has_finalize;
5351 /* Interfaces and valuetypes are not supposed to have finalizers */
5352 if (!(MONO_CLASS_IS_INTERFACE (klass) || klass->valuetype)) {
5353 MonoMethod *cmethod = NULL;
5355 if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5356 } else if (mono_class_is_ginst (klass)) {
5357 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5359 has_finalize = mono_class_has_finalizer (gklass);
5360 } else if (klass->parent && klass->parent->has_finalize) {
5361 has_finalize = TRUE;
5363 if (klass->parent) {
5365 * Can't search in metadata for a method named Finalize, because that
5366 * ignores overrides.
5368 mono_class_setup_vtable (klass);
5369 if (mono_class_has_failure (klass))
5372 cmethod = klass->vtable [finalize_slot];
5376 g_assert (klass->vtable_size > finalize_slot);
5378 if (klass->parent) {
5379 if (cmethod->is_inflated)
5380 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5381 if (cmethod != default_finalize)
5382 has_finalize = TRUE;
5388 mono_image_lock (klass->image);
5390 if (!klass->has_finalize_inited) {
5391 klass->has_finalize = has_finalize ? 1 : 0;
5393 mono_memory_barrier ();
5394 klass->has_finalize_inited = TRUE;
5397 mono_image_unlock (klass->image);
5399 return klass->has_finalize;
5403 mono_is_corlib_image (MonoImage *image)
5405 return image == mono_defaults.corlib;
5409 * LOCKING: this assumes the loader lock is held
5412 mono_class_setup_mono_type (MonoClass *klass)
5414 const char *name = klass->name;
5415 const char *nspace = klass->name_space;
5416 gboolean is_corlib = mono_is_corlib_image (klass->image);
5418 klass->this_arg.byref = 1;
5419 klass->this_arg.data.klass = klass;
5420 klass->this_arg.type = MONO_TYPE_CLASS;
5421 klass->byval_arg.data.klass = klass;
5422 klass->byval_arg.type = MONO_TYPE_CLASS;
5424 if (is_corlib && !strcmp (nspace, "System")) {
5425 if (!strcmp (name, "ValueType")) {
5427 * do not set the valuetype bit for System.ValueType.
5428 * klass->valuetype = 1;
5430 klass->blittable = TRUE;
5431 } else if (!strcmp (name, "Enum")) {
5433 * do not set the valuetype bit for System.Enum.
5434 * klass->valuetype = 1;
5436 klass->valuetype = 0;
5437 klass->enumtype = 0;
5438 } else if (!strcmp (name, "Object")) {
5439 klass->byval_arg.type = MONO_TYPE_OBJECT;
5440 klass->this_arg.type = MONO_TYPE_OBJECT;
5441 } else if (!strcmp (name, "String")) {
5442 klass->byval_arg.type = MONO_TYPE_STRING;
5443 klass->this_arg.type = MONO_TYPE_STRING;
5444 } else if (!strcmp (name, "TypedReference")) {
5445 klass->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5446 klass->this_arg.type = MONO_TYPE_TYPEDBYREF;
5450 if (klass->valuetype) {
5451 int t = MONO_TYPE_VALUETYPE;
5453 if (is_corlib && !strcmp (nspace, "System")) {
5456 if (!strcmp (name, "Boolean")) {
5457 t = MONO_TYPE_BOOLEAN;
5458 } else if (!strcmp(name, "Byte")) {
5460 klass->blittable = TRUE;
5464 if (!strcmp (name, "Char")) {
5469 if (!strcmp (name, "Double")) {
5471 klass->blittable = TRUE;
5475 if (!strcmp (name, "Int32")) {
5477 klass->blittable = TRUE;
5478 } else if (!strcmp(name, "Int16")) {
5480 klass->blittable = TRUE;
5481 } else if (!strcmp(name, "Int64")) {
5483 klass->blittable = TRUE;
5484 } else if (!strcmp(name, "IntPtr")) {
5486 klass->blittable = TRUE;
5490 if (!strcmp (name, "Single")) {
5492 klass->blittable = TRUE;
5493 } else if (!strcmp(name, "SByte")) {
5495 klass->blittable = TRUE;
5499 if (!strcmp (name, "UInt32")) {
5501 klass->blittable = TRUE;
5502 } else if (!strcmp(name, "UInt16")) {
5504 klass->blittable = TRUE;
5505 } else if (!strcmp(name, "UInt64")) {
5507 klass->blittable = TRUE;
5508 } else if (!strcmp(name, "UIntPtr")) {
5510 klass->blittable = TRUE;
5514 if (!strcmp (name, "TypedReference")) {
5515 t = MONO_TYPE_TYPEDBYREF;
5516 klass->blittable = TRUE;
5520 if (!strcmp (name, "Void")) {
5528 klass->byval_arg.type = (MonoTypeEnum)t;
5529 klass->this_arg.type = (MonoTypeEnum)t;
5532 if (MONO_CLASS_IS_INTERFACE (klass))
5533 klass->interface_id = mono_get_unique_iid (klass);
5538 * COM initialization is delayed until needed.
5539 * However when a [ComImport] attribute is present on a type it will trigger
5540 * the initialization. This is not a problem unless the BCL being executed
5541 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5544 init_com_from_comimport (MonoClass *klass)
5546 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5547 if (mono_security_core_clr_enabled ()) {
5548 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5549 if (!mono_security_core_clr_determine_platform_image (klass->image)) {
5550 /* but it can not be made available for application (i.e. user code) since all COM calls
5551 * are considered native calls. In this case we fail with a TypeLoadException (just like
5552 * Silverlight 2 does */
5553 mono_class_set_type_load_failure (klass, "");
5558 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5560 #endif /*DISABLE_COM*/
5563 * LOCKING: this assumes the loader lock is held
5566 mono_class_setup_parent (MonoClass *klass, MonoClass *parent)
5568 gboolean system_namespace;
5569 gboolean is_corlib = mono_is_corlib_image (klass->image);
5571 system_namespace = !strcmp (klass->name_space, "System") && is_corlib;
5573 /* if root of the hierarchy */
5574 if (system_namespace && !strcmp (klass->name, "Object")) {
5575 klass->parent = NULL;
5576 klass->instance_size = sizeof (MonoObject);
5579 if (!strcmp (klass->name, "<Module>")) {
5580 klass->parent = NULL;
5581 klass->instance_size = 0;
5585 if (!MONO_CLASS_IS_INTERFACE (klass)) {
5586 /* Imported COM Objects always derive from __ComObject. */
5588 if (MONO_CLASS_IS_IMPORT (klass)) {
5589 init_com_from_comimport (klass);
5590 if (parent == mono_defaults.object_class)
5591 parent = mono_class_get_com_object_class ();
5595 /* set the parent to something useful and safe, but mark the type as broken */
5596 parent = mono_defaults.object_class;
5597 mono_class_set_type_load_failure (klass, "");
5601 klass->parent = parent;
5603 if (mono_class_is_ginst (parent) && !parent->name) {
5605 * If the parent is a generic instance, we may get
5606 * called before it is fully initialized, especially
5607 * before it has its name.
5612 #ifndef DISABLE_REMOTING
5613 klass->marshalbyref = parent->marshalbyref;
5614 klass->contextbound = parent->contextbound;
5617 klass->delegate = parent->delegate;
5619 if (MONO_CLASS_IS_IMPORT (klass) || mono_class_is_com_object (parent))
5620 mono_class_set_is_com_object (klass);
5622 if (system_namespace) {
5623 #ifndef DISABLE_REMOTING
5624 if (klass->name [0] == 'M' && !strcmp (klass->name, "MarshalByRefObject"))
5625 klass->marshalbyref = 1;
5627 if (klass->name [0] == 'C' && !strcmp (klass->name, "ContextBoundObject"))
5628 klass->contextbound = 1;
5630 if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate"))
5631 klass->delegate = 1;
5634 if (klass->parent->enumtype || (mono_is_corlib_image (klass->parent->image) && (strcmp (klass->parent->name, "ValueType") == 0) &&
5635 (strcmp (klass->parent->name_space, "System") == 0)))
5636 klass->valuetype = 1;
5637 if (mono_is_corlib_image (klass->parent->image) && ((strcmp (klass->parent->name, "Enum") == 0) && (strcmp (klass->parent->name_space, "System") == 0))) {
5638 klass->valuetype = klass->enumtype = 1;
5640 /*klass->enumtype = klass->parent->enumtype; */
5642 /* initialize com types if COM interfaces are present */
5644 if (MONO_CLASS_IS_IMPORT (klass))
5645 init_com_from_comimport (klass);
5647 klass->parent = NULL;
5653 * mono_class_setup_supertypes:
5656 * Build the data structure needed to make fast type checks work.
5657 * This currently sets two fields in @class:
5658 * - idepth: distance between @class and System.Object in the type
5660 * - supertypes: array of classes: each element has a class in the hierarchy
5661 * starting from @class up to System.Object
5663 * LOCKING: This function is atomic, in case of contention we waste memory.
5666 mono_class_setup_supertypes (MonoClass *klass)
5669 MonoClass **supertypes;
5671 mono_atomic_load_acquire (supertypes, MonoClass **, &klass->supertypes);
5675 if (klass->parent && !klass->parent->supertypes)
5676 mono_class_setup_supertypes (klass->parent);
5678 klass->idepth = klass->parent->idepth + 1;
5682 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, klass->idepth);
5683 supertypes = (MonoClass **)mono_class_alloc0 (klass, sizeof (MonoClass *) * ms);
5685 if (klass->parent) {
5686 CHECKED_METADATA_WRITE_PTR ( supertypes [klass->idepth - 1] , klass );
5689 for (supertype_idx = 0; supertype_idx < klass->parent->idepth; supertype_idx++)
5690 CHECKED_METADATA_WRITE_PTR ( supertypes [supertype_idx] , klass->parent->supertypes [supertype_idx] );
5692 CHECKED_METADATA_WRITE_PTR ( supertypes [0] , klass );
5695 CHECKED_METADATA_WRITE_PTR_ATOMIC ( klass->supertypes , supertypes );
5699 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5701 MonoClass *gtd = (MonoClass*)user_data;
5702 /* Only try to fix generic instances of @gtd */
5703 if (mono_class_get_generic_class (gclass)->container_class != gtd)
5706 /* Check if the generic instance has no parent. */
5707 if (gtd->parent && !gclass->parent)
5708 mono_generic_class_setup_parent (gclass, gtd);
5714 mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char *msg)
5716 mono_class_set_type_load_failure (klass, "%s", msg);
5717 mono_error_set_type_load_class (error, klass, "%s", msg);
5721 * mono_class_create_from_typedef:
5722 * @image: image where the token is valid
5723 * @type_token: typedef token
5724 * @error: used to return any error found while creating the type
5726 * Create the MonoClass* representing the specified type token.
5727 * @type_token must be a TypeDef token.
5729 * FIXME: don't return NULL on failure, just the the caller figure it out.
5732 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5734 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5735 MonoClass *klass, *parent = NULL;
5736 guint32 cols [MONO_TYPEDEF_SIZE];
5737 guint32 cols_next [MONO_TYPEDEF_SIZE];
5738 guint tidx = mono_metadata_token_index (type_token);
5739 MonoGenericContext *context = NULL;
5740 const char *name, *nspace;
5742 MonoClass **interfaces;
5743 guint32 field_last, method_last;
5744 guint32 nesting_tokeen;
5746 mono_error_init (error);
5748 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5749 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5753 mono_loader_lock ();
5755 if ((klass = (MonoClass *)mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5756 mono_loader_unlock ();
5760 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5762 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5763 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5765 if (mono_metadata_has_generic_params (image, type_token)) {
5766 klass = mono_image_alloc0 (image, sizeof (MonoClassGtd));
5767 klass->class_kind = MONO_CLASS_GTD;
5768 classes_size += sizeof (MonoClassGtd);
5771 klass = mono_image_alloc0 (image, sizeof (MonoClassDef));
5772 klass->class_kind = MONO_CLASS_DEF;
5773 classes_size += sizeof (MonoClassDef);
5778 klass->name_space = nspace;
5780 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5782 klass->image = image;
5783 klass->type_token = type_token;
5784 mono_class_set_flags (klass, cols [MONO_TYPEDEF_FLAGS]);
5786 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
5789 * Check whether we're a generic type definition.
5791 if (mono_class_is_gtd (klass)) {
5792 MonoGenericContainer *generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
5793 generic_container->owner.klass = klass;
5794 generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
5795 context = &generic_container->context;
5796 mono_class_set_generic_container (klass, generic_container);
5797 enable_gclass_recording ();
5800 if (cols [MONO_TYPEDEF_EXTENDS]) {
5802 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5804 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5805 /*WARNING: this must satisfy mono_metadata_type_hash*/
5806 klass->this_arg.byref = 1;
5807 klass->this_arg.data.klass = klass;
5808 klass->this_arg.type = MONO_TYPE_CLASS;
5809 klass->byval_arg.data.klass = klass;
5810 klass->byval_arg.type = MONO_TYPE_CLASS;
5812 parent = mono_class_get_checked (image, parent_token, error);
5813 if (parent && context) /* Always inflate */
5814 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5816 if (parent == NULL) {
5817 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5818 goto parent_failure;
5821 for (tmp = parent; tmp; tmp = tmp->parent) {
5823 mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
5824 goto parent_failure;
5826 if (mono_class_is_gtd (klass) && mono_class_is_ginst (tmp) && mono_class_get_generic_class (tmp)->container_class == klass) {
5827 mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
5828 goto parent_failure;
5833 mono_class_setup_parent (klass, parent);
5835 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5836 mono_class_setup_mono_type (klass);
5838 if (mono_class_is_gtd (klass))
5839 disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
5842 * This might access klass->byval_arg for recursion generated by generic constraints,
5843 * so it has to come after setup_mono_type ().
5845 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5846 klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5847 if (!mono_error_ok (error)) {
5848 /*FIXME implement a mono_class_set_failure_from_mono_error */
5849 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5850 mono_loader_unlock ();
5851 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5856 if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5860 if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5864 klass->cast_class = klass->element_class = klass;
5866 if (!klass->enumtype) {
5867 if (!mono_metadata_interfaces_from_typedef_full (
5868 image, type_token, &interfaces, &icount, FALSE, context, error)){
5870 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5871 mono_loader_unlock ();
5872 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5876 klass->interfaces = interfaces;
5877 klass->interface_count = icount;
5878 klass->interfaces_inited = 1;
5881 /*g_print ("Load class %s\n", name);*/
5884 * Compute the field and method lists
5886 int first_field_idx = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5887 mono_class_set_first_field_idx (klass, first_field_idx);
5888 int first_method_idx = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5889 mono_class_set_first_method_idx (klass, first_method_idx);
5891 if (tt->rows > tidx){
5892 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5893 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5894 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5896 field_last = image->tables [MONO_TABLE_FIELD].rows;
5897 method_last = image->tables [MONO_TABLE_METHOD].rows;
5900 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5901 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5902 klass->field.count = field_last - first_field_idx;
5904 klass->field.count = 0;
5906 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5907 klass->method.count = method_last - first_method_idx;
5909 klass->method.count = 0;
5911 /* reserve space to store vector pointer in arrays */
5912 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5913 klass->instance_size += 2 * sizeof (gpointer);
5914 g_assert (klass->field.count == 0);
5917 if (klass->enumtype) {
5918 MonoType *enum_basetype = mono_class_find_enum_basetype (klass, error);
5919 if (!enum_basetype) {
5920 /*set it to a default value as the whole runtime can't handle this to be null*/
5921 klass->cast_class = klass->element_class = mono_defaults.int32_class;
5922 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5923 mono_loader_unlock ();
5924 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5927 klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
5931 * If we're a generic type definition, load the constraints.
5932 * We must do this after the class has been constructed to make certain recursive scenarios
5935 if (mono_class_is_gtd (klass) && !mono_metadata_load_generic_param_constraints_checked (image, type_token, mono_class_get_generic_container (klass), error)) {
5936 mono_class_set_type_load_failure (klass, "Could not load generic parameter constrains due to %s", mono_error_get_message (error));
5937 mono_loader_unlock ();
5938 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5942 if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5943 if (!strncmp (name, "Vector", 6))
5944 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");
5947 mono_loader_unlock ();
5949 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5954 mono_class_setup_mono_type (klass);
5955 mono_loader_unlock ();
5956 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5960 /** Is klass a Nullable<T> ginst? */
5962 mono_class_is_nullable (MonoClass *klass)
5964 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
5965 return gklass && gklass->container_class == mono_defaults.generic_nullable_class;
5969 /** if klass is T? return T */
5971 mono_class_get_nullable_param (MonoClass *klass)
5973 g_assert (mono_class_is_nullable (klass));
5974 return mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
5978 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5982 MonoGenericClass *gclass = mono_class_get_generic_class (klass);
5984 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5985 if (!mono_error_ok (&error)) {
5986 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5987 klass->parent = mono_defaults.object_class;
5988 mono_class_set_type_load_failure (klass, "Parent is a generic type instantiation that failed due to: %s", mono_error_get_message (&error));
5989 mono_error_cleanup (&error);
5993 mono_class_setup_parent (klass, klass->parent);
5995 if (klass->enumtype) {
5996 klass->cast_class = gtd->cast_class;
5997 klass->element_class = gtd->element_class;
6003 * Create the `MonoClass' for an instantiation of a generic type.
6004 * We only do this if we actually need it.
6007 mono_generic_class_get_class (MonoGenericClass *gclass)
6009 MonoClass *klass, *gklass;
6011 if (gclass->cached_class)
6012 return gclass->cached_class;
6014 mono_loader_lock ();
6015 if (gclass->cached_class) {
6016 mono_loader_unlock ();
6017 return gclass->cached_class;
6020 klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClassGenericInst));
6022 gklass = gclass->container_class;
6024 if (record_gclass_instantiation > 0)
6025 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
6027 if (gklass->nested_in) {
6028 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
6029 klass->nested_in = gklass->nested_in;
6032 klass->name = gklass->name;
6033 klass->name_space = gklass->name_space;
6035 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6037 klass->image = gklass->image;
6038 klass->type_token = gklass->type_token;
6039 klass->field.count = gklass->field.count;
6041 klass->class_kind = MONO_CLASS_GINST;
6043 ((MonoClassGenericInst*)klass)->generic_class = gclass;
6045 klass->byval_arg.type = MONO_TYPE_GENERICINST;
6046 klass->this_arg.type = klass->byval_arg.type;
6047 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
6048 klass->this_arg.byref = TRUE;
6049 klass->enumtype = gklass->enumtype;
6050 klass->valuetype = gklass->valuetype;
6052 klass->cast_class = klass->element_class = klass;
6054 if (mono_class_is_nullable (klass))
6055 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
6058 * We're not interested in the nested classes of a generic instance.
6059 * We use the generic type definition to look for nested classes.
6062 mono_generic_class_setup_parent (klass, gklass);
6064 if (gclass->is_dynamic) {
6066 * 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.
6067 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
6068 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
6070 if (!gklass->wastypebuilder)
6073 mono_class_setup_supertypes (klass);
6075 if (klass->enumtype) {
6077 * For enums, gklass->fields might not been set, but instance_size etc. is
6078 * already set in mono_reflection_create_internal_class (). For non-enums,
6079 * these will be computed normally in mono_class_layout_fields ().
6081 klass->instance_size = gklass->instance_size;
6082 klass->sizes.class_size = gklass->sizes.class_size;
6083 mono_memory_barrier ();
6084 klass->size_inited = 1;
6088 mono_memory_barrier ();
6089 gclass->cached_class = klass;
6091 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6093 ++class_ginst_count;
6094 inflated_classes_size += sizeof (MonoClassGenericInst);
6096 mono_loader_unlock ();
6102 get_image_for_container (MonoGenericContainer *container)
6105 if (container->is_anonymous) {
6106 result = container->owner.image;
6109 if (container->is_method) {
6110 MonoMethod *method = container->owner.method;
6111 g_assert_checked (method);
6112 klass = method->klass;
6114 klass = container->owner.klass;
6116 g_assert_checked (klass);
6117 result = klass->image;
6124 get_image_for_generic_param (MonoGenericParam *param)
6126 MonoGenericContainer *container = mono_generic_param_owner (param);
6127 g_assert_checked (container);
6128 return get_image_for_container (container);
6131 // Make a string in the designated image consisting of a single integer.
6132 #define INT_STRING_SIZE 16
6134 make_generic_name_string (MonoImage *image, int num)
6136 char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
6137 g_snprintf (name, INT_STRING_SIZE, "%d", num);
6141 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
6142 // pinfo is derived from param by the caller for us.
6144 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
6146 MonoClass *klass, **ptr;
6148 MonoGenericContainer *container = mono_generic_param_owner (param);
6149 g_assert_checked (container);
6151 MonoImage *image = get_image_for_container (container);
6152 gboolean is_mvar = container->is_method;
6153 gboolean is_anonymous = container->is_anonymous;
6155 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassGenericParam));
6156 klass->class_kind = MONO_CLASS_GPARAM;
6157 classes_size += sizeof (MonoClassGenericParam);
6158 ++class_gparam_count;
6161 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
6163 int n = mono_generic_param_num (param);
6164 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
6168 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , "" );
6169 } else if (is_mvar) {
6170 MonoMethod *omethod = container->owner.method;
6171 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
6173 MonoClass *oklass = container->owner.klass;
6174 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
6177 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6179 // Count non-NULL items in pinfo->constraints
6182 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6186 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6187 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
6189 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
6190 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
6192 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
6195 if (count - pos > 0) {
6196 klass->interface_count = count - pos;
6197 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
6198 klass->interfaces_inited = TRUE;
6199 for (i = pos; i < count; i++)
6200 CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
6203 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
6205 klass->inited = TRUE;
6206 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class , klass );
6207 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
6209 klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6210 klass->this_arg.type = klass->byval_arg.type;
6211 CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param , param );
6212 CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
6213 klass->this_arg.byref = TRUE;
6215 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6216 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6218 /*Init these fields to sane values*/
6219 klass->min_align = 1;
6221 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6222 * constrained to, the JIT depends on this.
6224 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6225 mono_memory_barrier ();
6226 klass->size_inited = 1;
6228 mono_class_setup_supertypes (klass);
6230 if (count - pos > 0) {
6231 mono_class_setup_vtable (klass->parent);
6232 if (mono_class_has_failure (klass->parent))
6233 mono_class_set_type_load_failure (klass, "Failed to setup parent interfaces");
6235 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6241 #define FAST_CACHE_SIZE 16
6244 * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6245 * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6246 * we cache the MonoClasses.
6247 * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6248 * LOCKING: Takes the image lock depending on @take_lock.
6251 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6253 int n = mono_generic_param_num (param);
6254 MonoImage *image = get_image_for_generic_param (param);
6255 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6256 MonoClass *klass = NULL;
6261 // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6262 // For high numbers or constraints we have to use pointer hashes.
6263 if (param->gshared_constraint) {
6264 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6267 mono_image_lock (image);
6268 klass = (MonoClass *)g_hash_table_lookup (ht, param);
6270 mono_image_unlock (image);
6275 if (n < FAST_CACHE_SIZE) {
6277 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6279 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6281 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6284 mono_image_lock (image);
6285 klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6287 mono_image_unlock (image);
6294 * LOCKING: Image lock (param->image) must be held
6297 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6299 int n = mono_generic_param_num (param);
6300 MonoImage *image = get_image_for_generic_param (param);
6301 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6305 if (param->gshared_constraint) {
6306 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6308 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6309 mono_memory_barrier ();
6311 image->mvar_cache_constrained = ht;
6313 image->var_cache_constrained = ht;
6315 g_hash_table_insert (ht, param, klass);
6316 } else if (n < FAST_CACHE_SIZE) {
6318 /* Requires locking to avoid droping an already published class */
6319 if (!image->mvar_cache_fast)
6320 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6321 image->mvar_cache_fast [n] = klass;
6323 if (!image->var_cache_fast)
6324 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6325 image->var_cache_fast [n] = klass;
6328 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6330 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6332 ht = g_hash_table_new (NULL, NULL);
6333 mono_memory_barrier ();
6335 image->mvar_cache_slow = ht;
6337 image->var_cache_slow = ht;
6340 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6345 * LOCKING: Acquires the image lock (@image).
6348 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6350 MonoImage *image = get_image_for_generic_param (param);
6351 MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6352 MonoClass *klass, *klass2;
6354 // If a klass already exists for this object and is cached, return it.
6355 if (pinfo) // Non-anonymous
6356 klass = pinfo->pklass;
6358 klass = get_anon_gparam_class (param, TRUE);
6363 // Create a new klass
6364 klass = make_generic_param_class (param, pinfo);
6366 // Now we need to cache the klass we created.
6367 // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6368 // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6369 // and allow our newly-created klass object to just leak.
6370 mono_memory_barrier ();
6372 mono_image_lock (image);
6374 // Here "klass2" refers to the klass potentially created by the other thread.
6375 if (pinfo) // Repeat check from above
6376 klass2 = pinfo->pklass;
6378 klass2 = get_anon_gparam_class (param, FALSE);
6385 pinfo->pklass = klass;
6387 set_anon_gparam_class (param, klass);
6389 mono_image_unlock (image);
6391 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6393 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED); // Alert profiler about botched class create
6395 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6401 * mono_class_from_generic_parameter:
6402 * @param: Parameter to find/construct a class for.
6403 * @arg2: Is ignored.
6404 * @arg3: Is ignored.
6407 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6409 return mono_class_from_generic_parameter_internal (param);
6414 mono_ptr_class_get (MonoType *type)
6417 MonoClass *el_class;
6421 el_class = mono_class_from_mono_type (type);
6422 image = el_class->image;
6424 mono_image_lock (image);
6425 if (image->ptr_cache) {
6426 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6427 mono_image_unlock (image);
6431 mono_image_unlock (image);
6433 result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassPointer));
6435 classes_size += sizeof (MonoClassPointer);
6436 ++class_pointer_count;
6438 result->parent = NULL; /* no parent for PTR types */
6439 result->name_space = el_class->name_space;
6440 name = g_strdup_printf ("%s*", el_class->name);
6441 result->name = mono_image_strdup (image, name);
6442 result->class_kind = MONO_CLASS_POINTER;
6445 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6447 result->image = el_class->image;
6448 result->inited = TRUE;
6449 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6450 result->cast_class = result->element_class = el_class;
6451 result->blittable = TRUE;
6453 result->byval_arg.type = MONO_TYPE_PTR;
6454 result->this_arg.type = result->byval_arg.type;
6455 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6456 result->this_arg.byref = TRUE;
6458 mono_class_setup_supertypes (result);
6460 mono_image_lock (image);
6461 if (image->ptr_cache) {
6463 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6464 mono_image_unlock (image);
6465 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6469 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6471 g_hash_table_insert (image->ptr_cache, el_class, result);
6472 mono_image_unlock (image);
6474 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6480 mono_fnptr_class_get (MonoMethodSignature *sig)
6483 static GHashTable *ptr_hash = NULL;
6485 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6487 mono_loader_lock ();
6490 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6492 if ((result = (MonoClass *)g_hash_table_lookup (ptr_hash, sig))) {
6493 mono_loader_unlock ();
6496 result = g_new0 (MonoClass, 1);
6498 classes_size += sizeof (MonoClassPointer);
6499 ++class_pointer_count;
6501 result->parent = NULL; /* no parent for PTR types */
6502 result->name_space = "System";
6503 result->name = "MonoFNPtrFakeClass";
6504 result->class_kind = MONO_CLASS_POINTER;
6506 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6508 result->image = mono_defaults.corlib; /* need to fix... */
6509 result->inited = TRUE;
6510 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6511 result->cast_class = result->element_class = result;
6512 result->blittable = TRUE;
6514 result->byval_arg.type = MONO_TYPE_FNPTR;
6515 result->this_arg.type = result->byval_arg.type;
6516 result->this_arg.data.method = result->byval_arg.data.method = sig;
6517 result->this_arg.byref = TRUE;
6518 result->blittable = TRUE;
6520 mono_class_setup_supertypes (result);
6522 g_hash_table_insert (ptr_hash, sig, result);
6524 mono_loader_unlock ();
6526 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6532 * mono_class_from_mono_type:
6533 * @type: describes the type to return
6535 * This returns a MonoClass for the specified MonoType, the value is never NULL.
6538 mono_class_from_mono_type (MonoType *type)
6540 switch (type->type) {
6541 case MONO_TYPE_OBJECT:
6542 return type->data.klass? type->data.klass: mono_defaults.object_class;
6543 case MONO_TYPE_VOID:
6544 return type->data.klass? type->data.klass: mono_defaults.void_class;
6545 case MONO_TYPE_BOOLEAN:
6546 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6547 case MONO_TYPE_CHAR:
6548 return type->data.klass? type->data.klass: mono_defaults.char_class;
6550 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6552 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6554 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6556 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6558 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6560 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6562 return type->data.klass? type->data.klass: mono_defaults.int_class;
6564 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6566 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6568 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6570 return type->data.klass? type->data.klass: mono_defaults.single_class;
6572 return type->data.klass? type->data.klass: mono_defaults.double_class;
6573 case MONO_TYPE_STRING:
6574 return type->data.klass? type->data.klass: mono_defaults.string_class;
6575 case MONO_TYPE_TYPEDBYREF:
6576 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6577 case MONO_TYPE_ARRAY:
6578 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6580 return mono_ptr_class_get (type->data.type);
6581 case MONO_TYPE_FNPTR:
6582 return mono_fnptr_class_get (type->data.method);
6583 case MONO_TYPE_SZARRAY:
6584 return mono_array_class_get (type->data.klass, 1);
6585 case MONO_TYPE_CLASS:
6586 case MONO_TYPE_VALUETYPE:
6587 return type->data.klass;
6588 case MONO_TYPE_GENERICINST:
6589 return mono_generic_class_get_class (type->data.generic_class);
6590 case MONO_TYPE_MVAR:
6592 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6594 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6595 g_assert_not_reached ();
6598 // Yes, this returns NULL, even if it is documented as not doing so, but there
6599 // is no way for the code to make it this far, due to the assert above.
6604 * mono_type_retrieve_from_typespec
6605 * @image: context where the image is created
6606 * @type_spec: typespec token
6607 * @context: the generic context used to evaluate generic instantiations in
6610 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6612 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6614 *did_inflate = FALSE;
6619 if (context && (context->class_inst || context->method_inst)) {
6620 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6622 if (!mono_error_ok (error)) {
6628 *did_inflate = TRUE;
6635 * mono_class_create_from_typespec
6636 * @image: context where the image is created
6637 * @type_spec: typespec token
6638 * @context: the generic context used to evaluate generic instantiations in
6641 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6644 gboolean inflated = FALSE;
6645 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6646 return_val_if_nok (error, NULL);
6647 ret = mono_class_from_mono_type (t);
6649 mono_metadata_free_type (t);
6654 * mono_bounded_array_class_get:
6655 * @element_class: element class
6656 * @rank: the dimension of the array class
6657 * @bounded: whenever the array has non-zero bounds
6659 * Returns: A class object describing the array with element type @element_type and
6663 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6667 MonoClass *parent = NULL;
6668 GSList *list, *rootlist = NULL;
6672 g_assert (rank <= 255);
6675 /* bounded only matters for one-dimensional arrays */
6678 image = eclass->image;
6680 if (rank == 1 && !bounded) {
6682 * This case is very frequent not just during compilation because of calls
6683 * from mono_class_from_mono_type (), mono_array_new (),
6684 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6686 mono_os_mutex_lock (&image->szarray_cache_lock);
6687 if (!image->szarray_cache)
6688 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6689 klass = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6690 mono_os_mutex_unlock (&image->szarray_cache_lock);
6694 mono_loader_lock ();
6696 mono_loader_lock ();
6698 if (!image->array_cache)
6699 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6701 if ((rootlist = list = (GSList *)g_hash_table_lookup (image->array_cache, eclass))) {
6702 for (; list; list = list->next) {
6703 klass = (MonoClass *)list->data;
6704 if ((klass->rank == rank) && (klass->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6705 mono_loader_unlock ();
6712 parent = mono_defaults.array_class;
6713 if (!parent->inited)
6714 mono_class_init (parent);
6716 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassArray));
6718 klass->image = image;
6719 klass->name_space = eclass->name_space;
6720 klass->class_kind = MONO_CLASS_ARRAY;
6722 nsize = strlen (eclass->name);
6723 name = (char *)g_malloc (nsize + 2 + rank + 1);
6724 memcpy (name, eclass->name, nsize);
6727 memset (name + nsize + 1, ',', rank - 1);
6729 name [nsize + rank] = '*';
6730 name [nsize + rank + bounded] = ']';
6731 name [nsize + rank + bounded + 1] = 0;
6732 klass->name = mono_image_strdup (image, name);
6735 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6737 classes_size += sizeof (MonoClassArray);
6738 ++class_array_count;
6740 klass->type_token = 0;
6741 klass->parent = parent;
6742 klass->instance_size = mono_class_instance_size (klass->parent);
6744 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6745 /*Arrays of those two types are invalid.*/
6746 MonoError prepared_error;
6747 mono_error_init (&prepared_error);
6748 mono_error_set_invalid_program (&prepared_error, "Arrays of void or System.TypedReference types are invalid.");
6749 mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6750 mono_error_cleanup (&prepared_error);
6751 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6752 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6753 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6754 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6756 /* element_size -1 is ok as this is not an instantitable type*/
6757 klass->sizes.element_size = -1;
6759 klass->sizes.element_size = mono_class_array_element_size (eclass);
6761 mono_class_setup_supertypes (klass);
6763 if (mono_class_is_ginst (eclass))
6764 mono_class_init (eclass);
6765 if (!eclass->size_inited)
6766 mono_class_setup_fields (eclass);
6767 mono_class_set_type_load_failure_causedby_class (klass, eclass, "Could not load array element type");
6768 /*FIXME we fail the array type, but we have to let other fields be set.*/
6770 klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6774 if (eclass->enumtype)
6775 klass->cast_class = eclass->element_class;
6777 klass->cast_class = eclass;
6779 switch (klass->cast_class->byval_arg.type) {
6781 klass->cast_class = mono_defaults.byte_class;
6784 klass->cast_class = mono_defaults.int16_class;
6787 #if SIZEOF_VOID_P == 4
6791 klass->cast_class = mono_defaults.int32_class;
6794 #if SIZEOF_VOID_P == 8
6798 klass->cast_class = mono_defaults.int64_class;
6804 klass->element_class = eclass;
6806 if ((rank > 1) || bounded) {
6807 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6808 klass->byval_arg.type = MONO_TYPE_ARRAY;
6809 klass->byval_arg.data.array = at;
6810 at->eklass = eclass;
6812 /* FIXME: complete.... */
6814 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6815 klass->byval_arg.data.klass = eclass;
6817 klass->this_arg = klass->byval_arg;
6818 klass->this_arg.byref = 1;
6820 //WTF was this? it's wrong
6821 // klass->generic_container = eclass->generic_container;
6823 if (rank == 1 && !bounded) {
6824 MonoClass *prev_class;
6826 mono_os_mutex_lock (&image->szarray_cache_lock);
6827 prev_class = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6829 /* Someone got in before us */
6832 g_hash_table_insert (image->szarray_cache, eclass, klass);
6833 mono_os_mutex_unlock (&image->szarray_cache_lock);
6835 list = g_slist_append (rootlist, klass);
6836 g_hash_table_insert (image->array_cache, eclass, list);
6839 mono_loader_unlock ();
6841 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6847 * mono_array_class_get:
6848 * @element_class: element class
6849 * @rank: the dimension of the array class
6851 * Returns: A class object describing the array with element type @element_type and
6855 mono_array_class_get (MonoClass *eclass, guint32 rank)
6857 return mono_bounded_array_class_get (eclass, rank, FALSE);
6861 * mono_class_instance_size:
6864 * Use to get the size of a class in bytes.
6866 * Returns: The size of an object instance
6869 mono_class_instance_size (MonoClass *klass)
6871 if (!klass->size_inited)
6872 mono_class_init (klass);
6874 return klass->instance_size;
6878 * mono_class_min_align:
6881 * Use to get the computed minimum alignment requirements for the specified class.
6883 * Returns: minimum alignment requirements
6886 mono_class_min_align (MonoClass *klass)
6888 if (!klass->size_inited)
6889 mono_class_init (klass);
6891 return klass->min_align;
6895 * mono_class_value_size:
6898 * This function is used for value types, and return the
6899 * space and the alignment to store that kind of value object.
6901 * Returns: the size of a value of kind @klass
6904 mono_class_value_size (MonoClass *klass, guint32 *align)
6908 /* fixme: check disable, because we still have external revereces to
6909 * mscorlib and Dummy Objects
6911 /*g_assert (klass->valuetype);*/
6913 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6916 *align = klass->min_align;
6922 * mono_class_data_size:
6925 * Returns: The size of the static class data
6928 mono_class_data_size (MonoClass *klass)
6931 mono_class_init (klass);
6932 /* This can happen with dynamically created types */
6933 if (!klass->fields_inited)
6934 mono_class_setup_fields (klass);
6936 /* in arrays, sizes.class_size is unioned with element_size
6937 * and arrays have no static fields
6941 return klass->sizes.class_size;
6945 * Auxiliary routine to mono_class_get_field
6947 * Takes a field index instead of a field token.
6949 static MonoClassField *
6950 mono_class_get_field_idx (MonoClass *klass, int idx)
6952 mono_class_setup_fields (klass);
6953 if (mono_class_has_failure (klass))
6957 int first_field_idx = mono_class_get_first_field_idx (klass);
6958 if (klass->image->uncompressed_metadata) {
6960 * first_field_idx points to the FieldPtr table, while idx points into the
6961 * Field table, so we have to do a search.
6963 /*FIXME this is broken for types with multiple fields with the same name.*/
6964 const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6967 for (i = 0; i < klass->field.count; ++i)
6968 if (mono_field_get_name (&klass->fields [i]) == name)
6969 return &klass->fields [i];
6970 g_assert_not_reached ();
6972 if (klass->field.count) {
6973 if ((idx >= first_field_idx) && (idx < first_field_idx + klass->field.count)){
6974 return &klass->fields [idx - first_field_idx];
6978 klass = klass->parent;
6984 * mono_class_get_field:
6985 * @class: the class to lookup the field.
6986 * @field_token: the field token
6988 * Returns: A MonoClassField representing the type and offset of
6989 * the field, or a NULL value if the field does not belong to this
6993 mono_class_get_field (MonoClass *klass, guint32 field_token)
6995 int idx = mono_metadata_token_index (field_token);
6997 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6999 return mono_class_get_field_idx (klass, idx - 1);
7003 * mono_class_get_field_from_name:
7004 * @klass: the class to lookup the field.
7005 * @name: the field name
7007 * Search the class @klass and it's parents for a field with the name @name.
7009 * Returns: The MonoClassField pointer of the named field or NULL
7012 mono_class_get_field_from_name (MonoClass *klass, const char *name)
7014 return mono_class_get_field_from_name_full (klass, name, NULL);
7018 * mono_class_get_field_from_name_full:
7019 * @klass: the class to lookup the field.
7020 * @name: the field name
7021 * @type: the type of the fields. This optional.
7023 * Search the class @klass and it's parents for a field with the name @name and type @type.
7025 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
7026 * of its generic type definition.
7028 * Returns: The MonoClassField pointer of the named field or NULL
7031 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
7035 mono_class_setup_fields (klass);
7036 if (mono_class_has_failure (klass))
7040 for (i = 0; i < klass->field.count; ++i) {
7041 MonoClassField *field = &klass->fields [i];
7043 if (strcmp (name, mono_field_get_name (field)) != 0)
7047 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
7048 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
7053 klass = klass->parent;
7059 * mono_class_get_field_token:
7060 * @field: the field we need the token of
7062 * Get the token of a field. Note that the tokesn is only valid for the image
7063 * the field was loaded from. Don't use this function for fields in dynamic types.
7065 * Returns: The token representing the field in the image it was loaded from.
7068 mono_class_get_field_token (MonoClassField *field)
7070 MonoClass *klass = field->parent;
7073 mono_class_setup_fields (klass);
7078 int first_field_idx = mono_class_get_first_field_idx (klass);
7079 for (i = 0; i < klass->field.count; ++i) {
7080 if (&klass->fields [i] == field) {
7081 int idx = first_field_idx + i + 1;
7083 if (klass->image->uncompressed_metadata)
7084 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
7085 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
7088 klass = klass->parent;
7091 g_assert_not_reached ();
7096 mono_field_get_index (MonoClassField *field)
7098 int index = field - field->parent->fields;
7100 g_assert (index >= 0 && index < field->parent->field.count);
7106 * mono_class_get_field_default_value:
7108 * Return the default value of the field as a pointer into the metadata blob.
7111 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
7114 guint32 constant_cols [MONO_CONSTANT_SIZE];
7116 MonoClass *klass = field->parent;
7118 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7120 if (!klass->ext || !klass->ext->field_def_values) {
7121 MonoFieldDefaultValue *def_values;
7123 mono_class_alloc_ext (klass);
7125 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
7127 mono_image_lock (klass->image);
7128 mono_memory_barrier ();
7129 if (!klass->ext->field_def_values)
7130 klass->ext->field_def_values = def_values;
7131 mono_image_unlock (klass->image);
7134 field_index = mono_field_get_index (field);
7136 if (!klass->ext->field_def_values [field_index].data) {
7137 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7141 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7143 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7144 klass->ext->field_def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7145 klass->ext->field_def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7148 *def_type = klass->ext->field_def_values [field_index].def_type;
7149 return klass->ext->field_def_values [field_index].data;
7153 mono_property_get_index (MonoProperty *prop)
7155 int index = prop - prop->parent->ext->properties;
7157 g_assert (index >= 0 && index < prop->parent->ext->property.count);
7163 * mono_class_get_property_default_value:
7165 * Return the default value of the field as a pointer into the metadata blob.
7168 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7171 guint32 constant_cols [MONO_CONSTANT_SIZE];
7172 MonoClass *klass = property->parent;
7174 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7176 * We don't cache here because it is not used by C# so it's quite rare, but
7177 * we still do the lookup in klass->ext because that is where the data
7178 * is stored for dynamic assemblies.
7181 if (image_is_dynamic (klass->image)) {
7182 int prop_index = mono_property_get_index (property);
7183 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
7184 *def_type = klass->ext->prop_def_values [prop_index].def_type;
7185 return klass->ext->prop_def_values [prop_index].data;
7189 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7193 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7194 *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7195 return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7199 mono_class_get_event_token (MonoEvent *event)
7201 MonoClass *klass = event->parent;
7206 for (i = 0; i < klass->ext->event.count; ++i) {
7207 if (&klass->ext->events [i] == event)
7208 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
7211 klass = klass->parent;
7214 g_assert_not_reached ();
7219 * mono_class_get_property_from_name:
7221 * @name: name of the property to lookup in the specified class
7223 * Use this method to lookup a property in a class
7224 * Returns: the MonoProperty with the given name, or NULL if the property
7225 * does not exist on the @klass.
7228 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7232 gpointer iter = NULL;
7233 while ((p = mono_class_get_properties (klass, &iter))) {
7234 if (! strcmp (name, p->name))
7237 klass = klass->parent;
7243 * mono_class_get_property_token:
7244 * @prop: MonoProperty to query
7246 * Returns: The ECMA token for the specified property.
7249 mono_class_get_property_token (MonoProperty *prop)
7251 MonoClass *klass = prop->parent;
7255 gpointer iter = NULL;
7256 while ((p = mono_class_get_properties (klass, &iter))) {
7257 if (&klass->ext->properties [i] == prop)
7258 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
7262 klass = klass->parent;
7265 g_assert_not_reached ();
7270 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7272 const char *name, *nspace;
7273 if (image_is_dynamic (image))
7274 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7276 switch (type_token & 0xff000000){
7277 case MONO_TOKEN_TYPE_DEF: {
7278 guint32 cols [MONO_TYPEDEF_SIZE];
7279 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7280 guint tidx = mono_metadata_token_index (type_token);
7282 if (tidx > tt->rows)
7283 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7285 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7286 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7287 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7288 if (strlen (nspace) == 0)
7289 return g_strdup_printf ("%s", name);
7291 return g_strdup_printf ("%s.%s", nspace, name);
7294 case MONO_TOKEN_TYPE_REF: {
7296 guint32 cols [MONO_TYPEREF_SIZE];
7297 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7298 guint tidx = mono_metadata_token_index (type_token);
7301 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7303 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7304 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7305 mono_error_cleanup (&error);
7309 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7310 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7311 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7312 if (strlen (nspace) == 0)
7313 return g_strdup_printf ("%s", name);
7315 return g_strdup_printf ("%s.%s", nspace, name);
7318 case MONO_TOKEN_TYPE_SPEC:
7319 return g_strdup_printf ("Typespec 0x%08x", type_token);
7321 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7326 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7328 if (image_is_dynamic (image))
7329 return g_strdup_printf ("DynamicAssembly %s", image->name);
7331 switch (type_token & 0xff000000){
7332 case MONO_TOKEN_TYPE_DEF:
7333 if (image->assembly)
7334 return mono_stringify_assembly_name (&image->assembly->aname);
7335 else if (image->assembly_name)
7336 return g_strdup (image->assembly_name);
7337 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7338 case MONO_TOKEN_TYPE_REF: {
7340 MonoAssemblyName aname;
7341 guint32 cols [MONO_TYPEREF_SIZE];
7342 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7343 guint32 idx = mono_metadata_token_index (type_token);
7346 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7348 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7349 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7350 mono_error_cleanup (&error);
7353 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7355 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7356 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7357 case MONO_RESOLUTION_SCOPE_MODULE:
7359 return g_strdup ("");
7360 case MONO_RESOLUTION_SCOPE_MODULEREF:
7362 return g_strdup ("");
7363 case MONO_RESOLUTION_SCOPE_TYPEREF:
7365 return g_strdup ("");
7366 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7367 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7368 return mono_stringify_assembly_name (&aname);
7370 g_assert_not_reached ();
7374 case MONO_TOKEN_TYPE_SPEC:
7376 return g_strdup ("");
7378 g_assert_not_reached ();
7385 * mono_class_get_full:
7386 * @image: the image where the class resides
7387 * @type_token: the token for the class
7388 * @context: the generic context used to evaluate generic instantiations in
7389 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7391 * Returns: The MonoClass that represents @type_token in @image
7394 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7398 klass = mono_class_get_checked (image, type_token, &error);
7400 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7401 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7403 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7409 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7413 mono_error_init (error);
7414 klass = mono_class_get_checked (image, type_token, error);
7416 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7417 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7422 * mono_class_get_checked:
7423 * @image: the image where the class resides
7424 * @type_token: the token for the class
7425 * @error: error object to return any error
7427 * Returns: The MonoClass that represents @type_token in @image, or NULL on error.
7430 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7432 MonoClass *klass = NULL;
7434 mono_error_init (error);
7436 if (image_is_dynamic (image)) {
7437 int table = mono_metadata_token_table (type_token);
7439 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7440 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7443 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
7447 switch (type_token & 0xff000000){
7448 case MONO_TOKEN_TYPE_DEF:
7449 klass = mono_class_create_from_typedef (image, type_token, error);
7451 case MONO_TOKEN_TYPE_REF:
7452 klass = mono_class_from_typeref_checked (image, type_token, error);
7454 case MONO_TOKEN_TYPE_SPEC:
7455 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7458 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7462 /* Generic case, should be avoided for when a better error is possible. */
7463 if (!klass && mono_error_ok (error)) {
7464 char *name = mono_class_name_from_token (image, type_token);
7465 char *assembly = mono_assembly_name_from_token (image, type_token);
7466 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7474 * mono_type_get_checked:
7475 * @image: the image where the type resides
7476 * @type_token: the token for the type
7477 * @context: the generic context used to evaluate generic instantiations in
7478 * @error: Error handling context
7480 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7482 * Returns: The MonoType that represents @type_token in @image
7485 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7487 MonoType *type = NULL;
7488 gboolean inflated = FALSE;
7490 mono_error_init (error);
7492 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7493 if (image_is_dynamic (image)) {
7494 MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
7495 return_val_if_nok (error, NULL);
7496 return mono_class_get_type (klass);
7499 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7500 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7507 return mono_class_get_type (klass);
7510 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7517 MonoType *tmp = type;
7518 type = mono_class_get_type (mono_class_from_mono_type (type));
7519 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7520 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7521 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7523 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7525 if (type->type != tmp->type)
7528 mono_metadata_free_type (tmp);
7535 * @image: image where the class token will be looked up.
7536 * @type_token: a type token from the image
7538 * Returns the MonoClass with the given @type_token on the @image
7541 mono_class_get (MonoImage *image, guint32 type_token)
7543 return mono_class_get_full (image, type_token, NULL);
7547 * mono_image_init_name_cache:
7549 * Initializes the class name cache stored in image->name_cache.
7551 * LOCKING: Acquires the corresponding image lock.
7554 mono_image_init_name_cache (MonoImage *image)
7556 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7557 guint32 cols [MONO_TYPEDEF_SIZE];
7560 guint32 i, visib, nspace_index;
7561 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7563 if (image->name_cache)
7566 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7568 if (image_is_dynamic (image)) {
7569 mono_image_lock (image);
7570 if (image->name_cache) {
7571 /* Somebody initialized it before us */
7572 g_hash_table_destroy (the_name_cache);
7574 mono_atomic_store_release (&image->name_cache, the_name_cache);
7576 mono_image_unlock (image);
7580 /* Temporary hash table to avoid lookups in the nspace_table */
7581 name_cache2 = g_hash_table_new (NULL, NULL);
7583 for (i = 1; i <= t->rows; ++i) {
7584 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7585 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7587 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7588 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7590 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7592 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7593 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7595 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7596 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7597 if (!nspace_table) {
7598 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7599 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7600 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7603 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7606 /* Load type names from EXPORTEDTYPES table */
7608 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7609 guint32 cols [MONO_EXP_TYPE_SIZE];
7612 for (i = 0; i < t->rows; ++i) {
7613 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7615 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7616 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7620 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7621 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7623 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7624 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7625 if (!nspace_table) {
7626 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7627 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7628 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7631 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7635 g_hash_table_destroy (name_cache2);
7637 mono_image_lock (image);
7638 if (image->name_cache) {
7639 /* Somebody initialized it before us */
7640 g_hash_table_destroy (the_name_cache);
7642 mono_atomic_store_release (&image->name_cache, the_name_cache);
7644 mono_image_unlock (image);
7647 /*FIXME Only dynamic assemblies should allow this operation.*/
7649 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7650 const char *name, guint32 index)
7652 GHashTable *nspace_table;
7653 GHashTable *name_cache;
7656 mono_image_init_name_cache (image);
7657 mono_image_lock (image);
7659 name_cache = image->name_cache;
7660 if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7661 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7662 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7665 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7666 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7668 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7670 mono_image_unlock (image);
7679 find_nocase (gpointer key, gpointer value, gpointer user_data)
7681 char *name = (char*)key;
7682 FindUserData *data = (FindUserData*)user_data;
7684 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7685 data->value = value;
7689 * mono_class_from_name_case:
7690 * @image: The MonoImage where the type is looked up in
7691 * @name_space: the type namespace
7692 * @name: the type short name.
7693 * @deprecated: use the mono_class_from_name_case_checked variant instead.
7695 * Obtains a MonoClass with a given namespace and a given name which
7696 * is located in the given MonoImage. The namespace and name
7697 * lookups are case insensitive.
7700 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7703 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7704 mono_error_cleanup (&error);
7710 * mono_class_from_name_case:
7711 * @image: The MonoImage where the type is looked up in
7712 * @name_space: the type namespace
7713 * @name: the type short name.
7716 * Obtains a MonoClass with a given namespace and a given name which
7717 * is located in the given MonoImage. The namespace and name
7718 * lookups are case insensitive.
7720 * Returns: The MonoClass if the given namespace and name were found, or NULL if it
7721 * was not found. The @error object will contain information about the problem
7725 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7727 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7728 guint32 cols [MONO_TYPEDEF_SIZE];
7733 mono_error_init (error);
7735 if (image_is_dynamic (image)) {
7737 FindUserData user_data;
7739 mono_image_init_name_cache (image);
7740 mono_image_lock (image);
7742 user_data.key = name_space;
7743 user_data.value = NULL;
7744 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7746 if (user_data.value) {
7747 GHashTable *nspace_table = (GHashTable*)user_data.value;
7749 user_data.key = name;
7750 user_data.value = NULL;
7752 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7754 if (user_data.value)
7755 token = GPOINTER_TO_UINT (user_data.value);
7758 mono_image_unlock (image);
7761 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7767 /* add a cache if needed */
7768 for (i = 1; i <= t->rows; ++i) {
7769 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7770 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7772 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7773 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7775 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7777 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7778 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7779 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7780 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7786 return_nested_in (MonoClass *klass, char *nested)
7789 char *s = strchr (nested, '/');
7790 gpointer iter = NULL;
7797 while ((found = mono_class_get_nested_types (klass, &iter))) {
7798 if (strcmp (found->name, nested) == 0) {
7800 return return_nested_in (found, s);
7808 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7810 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7811 MonoImage *file_image;
7815 mono_error_init (error);
7818 * The EXPORTEDTYPES table only contains public types, so have to search the
7820 * Note: image->modules contains the contents of the MODULEREF table, while
7821 * the real module list is in the FILE table.
7823 for (i = 0; i < file_table->rows; i++) {
7824 guint32 cols [MONO_FILE_SIZE];
7825 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7826 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7829 file_image = mono_image_load_file_for_image_checked (image, i + 1, error);
7831 klass = mono_class_from_name_checked (file_image, name_space, name, error);
7832 if (klass || !is_ok (error))
7841 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7843 GHashTable *nspace_table;
7844 MonoImage *loaded_image;
7851 mono_error_init (error);
7853 // Checking visited images avoids stack overflows when cyclic references exist.
7854 if (g_hash_table_lookup (visited_images, image))
7857 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7859 if ((nested = strchr (name, '/'))) {
7860 int pos = nested - name;
7861 int len = strlen (name);
7864 memcpy (buf, name, len + 1);
7866 nested = buf + pos + 1;
7870 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7871 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7872 gboolean res = get_class_from_name (image, name_space, name, &klass);
7875 klass = search_modules (image, name_space, name, error);
7880 return klass ? return_nested_in (klass, nested) : NULL;
7886 mono_image_init_name_cache (image);
7887 mono_image_lock (image);
7889 nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7892 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7894 mono_image_unlock (image);
7896 if (!token && image_is_dynamic (image) && image->modules) {
7897 /* Search modules as well */
7898 for (i = 0; i < image->module_count; ++i) {
7899 MonoImage *module = image->modules [i];
7901 klass = mono_class_from_name_checked (module, name_space, name, error);
7902 if (klass || !is_ok (error))
7908 klass = search_modules (image, name_space, name, error);
7909 if (klass || !is_ok (error))
7914 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7915 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7916 guint32 cols [MONO_EXP_TYPE_SIZE];
7919 idx = mono_metadata_token_index (token);
7921 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7923 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7924 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7925 loaded_image = mono_assembly_load_module_checked (image->assembly, impl >> MONO_IMPLEMENTATION_BITS, error);
7928 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7930 return klass ? return_nested_in (klass, nested) : NULL;
7932 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7933 guint32 assembly_idx;
7935 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7937 mono_assembly_load_reference (image, assembly_idx - 1);
7938 g_assert (image->references [assembly_idx - 1]);
7939 if (image->references [assembly_idx - 1] == (gpointer)-1)
7941 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
7943 return klass ? return_nested_in (klass, nested) : NULL;
7946 g_assert_not_reached ();
7950 token = MONO_TOKEN_TYPE_DEF | token;
7952 klass = mono_class_get_checked (image, token, error);
7954 return return_nested_in (klass, nested);
7959 * mono_class_from_name_checked:
7960 * @image: The MonoImage where the type is looked up in
7961 * @name_space: the type namespace
7962 * @name: the type short name.
7964 * Obtains a MonoClass with a given namespace and a given name which
7965 * is located in the given MonoImage.
7967 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
7968 * set if the class was not found or it will return NULL and set the error if there was a loading error.
7971 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7974 GHashTable *visited_images;
7976 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7978 klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
7980 g_hash_table_destroy (visited_images);
7986 * mono_class_from_name:
7987 * @image: The MonoImage where the type is looked up in
7988 * @name_space: the type namespace
7989 * @name: the type short name.
7991 * Obtains a MonoClass with a given namespace and a given name which
7992 * is located in the given MonoImage.
7994 * To reference nested classes, use the "/" character as a separator.
7995 * For example use "Foo/Bar" to reference the class Bar that is nested
7996 * inside Foo, like this: "class Foo { class Bar {} }".
7999 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
8004 klass = mono_class_from_name_checked (image, name_space, name, &error);
8005 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
8011 * mono_class_load_from_name:
8012 * @image: The MonoImage where the type is looked up in
8013 * @name_space: the type namespace
8014 * @name: the type short name.
8016 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
8017 * This function should be used by the runtime for critical types to which there's no way to recover but crash
8018 * If they are missing. Thing of System.Object or System.String.
8021 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
8026 klass = mono_class_from_name_checked (image, name_space, name, &error);
8028 g_error ("Runtime critical type %s.%s not found", name_space, name);
8029 if (!mono_error_ok (&error))
8030 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8035 * mono_class_try_load_from_name:
8036 * @image: The MonoImage where the type is looked up in
8037 * @name_space: the type namespace
8038 * @name: the type short name.
8040 * This function tries to load a type, returning the class was found or NULL otherwise.
8041 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
8043 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
8044 * a type that we would otherwise assume to be available but was not due some error.
8048 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
8053 klass = mono_class_from_name_checked (image, name_space, name, &error);
8054 if (!mono_error_ok (&error))
8055 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8061 * mono_class_is_subclass_of:
8062 * @klass: class to probe if it is a subclass of another one
8063 * @klassc: the class we suspect is the base class
8064 * @check_interfaces: whether we should perform interface checks
8066 * This method determines whether @klass is a subclass of @klassc.
8068 * If the @check_interfaces flag is set, then if @klassc is an interface
8069 * this method return TRUE if the @klass implements the interface or
8070 * if @klass is an interface, if one of its base classes is @klass.
8072 * If @check_interfaces is false then, then if @klass is not an interface
8073 * then it returns TRUE if the @klass is a subclass of @klassc.
8075 * if @klass is an interface and @klassc is System.Object, then this function
8080 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
8081 gboolean check_interfaces)
8083 /* FIXME test for interfaces with variant generic arguments */
8084 mono_class_init (klass);
8085 mono_class_init (klassc);
8087 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
8088 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
8090 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
8093 for (i = 0; i < klass->interface_count; i ++) {
8094 MonoClass *ic = klass->interfaces [i];
8099 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
8104 * MS.NET thinks interfaces are a subclass of Object, so we think it as
8107 if (klassc == mono_defaults.object_class)
8114 mono_type_is_generic_argument (MonoType *type)
8116 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
8120 mono_class_has_variant_generic_params (MonoClass *klass)
8123 MonoGenericContainer *container;
8125 if (!mono_class_is_ginst (klass))
8128 container = mono_class_get_generic_container (mono_class_get_generic_class (klass)->container_class);
8130 for (i = 0; i < container->type_argc; ++i)
8131 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8138 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8140 if (target == candidate)
8143 if (check_for_reference_conv &&
8144 mono_type_is_generic_argument (&target->byval_arg) &&
8145 mono_type_is_generic_argument (&candidate->byval_arg)) {
8146 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8147 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8149 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8152 if (!mono_class_is_assignable_from (target, candidate))
8158 * @container the generic container from the GTD
8159 * @klass: the class to be assigned to
8160 * @oklass: the source class
8162 * Both @klass and @oklass must be instances of the same generic interface.
8164 * Returns: TRUE if @klass can be assigned to a @klass variable
8167 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8170 MonoType **klass_argv, **oklass_argv;
8171 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8172 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8174 if (klass == oklass)
8177 /*Viable candidates are instances of the same generic interface*/
8178 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8181 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8182 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8184 for (j = 0; j < container->type_argc; ++j) {
8185 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8186 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8188 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8192 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8193 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8195 if (param1_class != param2_class) {
8196 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8197 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8199 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8200 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8210 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8212 MonoGenericParam *gparam, *ogparam;
8213 MonoGenericParamInfo *tinfo, *cinfo;
8214 MonoClass **candidate_class;
8215 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8218 if (target == candidate)
8220 if (target->byval_arg.type != candidate->byval_arg.type)
8223 gparam = target->byval_arg.data.generic_param;
8224 ogparam = candidate->byval_arg.data.generic_param;
8225 tinfo = mono_generic_param_info (gparam);
8226 cinfo = mono_generic_param_info (ogparam);
8228 class_constraint_satisfied = FALSE;
8229 valuetype_constraint_satisfied = FALSE;
8231 /*candidate must have a super set of target's special constraints*/
8232 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8233 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8235 if (cinfo->constraints) {
8236 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8237 MonoClass *cc = *candidate_class;
8239 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8240 class_constraint_satisfied = TRUE;
8241 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8242 valuetype_constraint_satisfied = TRUE;
8245 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8246 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8248 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8250 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8252 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8253 valuetype_constraint_satisfied)) {
8258 /*candidate type constraints must be a superset of target's*/
8259 if (tinfo->constraints) {
8260 MonoClass **target_class;
8261 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8262 MonoClass *tc = *target_class;
8265 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8266 * check it's constraints since it satisfy the constraint by itself.
8268 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8271 if (!cinfo->constraints)
8274 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8275 MonoClass *cc = *candidate_class;
8277 if (mono_class_is_assignable_from (tc, cc))
8281 * This happens when we have the following:
8283 * Bar<K> where K : IFace
8284 * Foo<T, U> where T : U where U : IFace
8286 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8289 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8290 if (mono_gparam_is_assignable_from (target, cc))
8294 if (!*candidate_class)
8299 /*candidate itself must have a constraint that satisfy target*/
8300 if (cinfo->constraints) {
8301 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8302 MonoClass *cc = *candidate_class;
8303 if (mono_class_is_assignable_from (target, cc))
8311 * mono_class_is_assignable_from:
8312 * @klass: the class to be assigned to
8313 * @oklass: the source class
8315 * Returns: TRUE if an instance of object oklass can be assigned to an
8316 * instance of object @klass
8319 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8322 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8324 mono_class_init (klass);
8326 if (!oklass->inited)
8327 mono_class_init (oklass);
8329 if (mono_class_has_failure (klass) || mono_class_has_failure (oklass))
8332 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8333 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8335 return mono_gparam_is_assignable_from (klass, oklass);
8338 if (MONO_CLASS_IS_INTERFACE (klass)) {
8339 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8340 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8341 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8345 for (i = 0; constraints [i]; ++i) {
8346 if (mono_class_is_assignable_from (klass, constraints [i]))
8354 /* interface_offsets might not be set for dynamic classes */
8355 if (oklass->ref_info_handle && !oklass->interface_bitmap) {
8357 * oklass might be a generic type parameter but they have
8358 * interface_offsets set.
8360 gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8361 if (!is_ok (&error)) {
8362 mono_error_cleanup (&error);
8367 if (!oklass->interface_bitmap)
8368 /* Happens with generic instances of not-yet created dynamic types */
8370 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8373 if (mono_class_has_variant_generic_params (klass)) {
8375 mono_class_setup_interfaces (oklass, &error);
8376 if (!mono_error_ok (&error)) {
8377 mono_error_cleanup (&error);
8381 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8382 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8383 MonoClass *iface = oklass->interfaces_packed [i];
8385 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8390 } else if (klass->delegate) {
8391 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8393 }else if (klass->rank) {
8394 MonoClass *eclass, *eoclass;
8396 if (oklass->rank != klass->rank)
8399 /* vectors vs. one dimensional arrays */
8400 if (oklass->byval_arg.type != klass->byval_arg.type)
8403 eclass = klass->cast_class;
8404 eoclass = oklass->cast_class;
8407 * a is b does not imply a[] is b[] when a is a valuetype, and
8408 * b is a reference type.
8411 if (eoclass->valuetype) {
8412 if ((eclass == mono_defaults.enum_class) ||
8413 (eclass == mono_defaults.enum_class->parent) ||
8414 (eclass == mono_defaults.object_class))
8418 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8419 } else if (mono_class_is_nullable (klass)) {
8420 if (mono_class_is_nullable (oklass))
8421 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8423 return mono_class_is_assignable_from (klass->cast_class, oklass);
8424 } else if (klass == mono_defaults.object_class)
8427 return mono_class_has_parent (oklass, klass);
8430 /*Check if @oklass is variant compatible with @klass.*/
8432 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8435 MonoType **klass_argv, **oklass_argv;
8436 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8437 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8439 /*Viable candidates are instances of the same generic interface*/
8440 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8443 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8444 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8446 for (j = 0; j < container->type_argc; ++j) {
8447 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8448 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8450 if (param1_class->valuetype != param2_class->valuetype)
8454 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8455 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8457 if (param1_class != param2_class) {
8458 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8459 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8461 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8462 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8470 /*Check if @candidate implements the interface @target*/
8472 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8476 gboolean is_variant = mono_class_has_variant_generic_params (target);
8478 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8479 if (mono_class_is_variant_compatible_slow (target, candidate))
8484 if (candidate == target)
8487 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8488 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8489 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (candidate);
8491 if (tb && tb->interfaces) {
8492 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8493 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8494 MonoClass *iface_class;
8496 /* we can't realize the type here since it can do pretty much anything. */
8499 iface_class = mono_class_from_mono_type (iface->type);
8500 if (iface_class == target)
8502 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8504 if (mono_class_implement_interface_slow (target, iface_class))
8509 /*setup_interfaces don't mono_class_init anything*/
8510 /*FIXME this doesn't handle primitive type arrays.
8511 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8512 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8514 mono_class_setup_interfaces (candidate, &error);
8515 if (!mono_error_ok (&error)) {
8516 mono_error_cleanup (&error);
8520 for (i = 0; i < candidate->interface_count; ++i) {
8521 if (candidate->interfaces [i] == target)
8524 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8527 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8531 candidate = candidate->parent;
8532 } while (candidate);
8538 * Check if @oklass can be assigned to @klass.
8539 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8542 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8544 if (candidate == target)
8546 if (target == mono_defaults.object_class)
8549 if (mono_class_has_parent (candidate, target))
8552 /*If target is not an interface there is no need to check them.*/
8553 if (MONO_CLASS_IS_INTERFACE (target))
8554 return mono_class_implement_interface_slow (target, candidate);
8556 if (target->delegate && mono_class_has_variant_generic_params (target))
8557 return mono_class_is_variant_compatible (target, candidate, FALSE);
8560 MonoClass *eclass, *eoclass;
8562 if (target->rank != candidate->rank)
8565 /* vectors vs. one dimensional arrays */
8566 if (target->byval_arg.type != candidate->byval_arg.type)
8569 eclass = target->cast_class;
8570 eoclass = candidate->cast_class;
8573 * a is b does not imply a[] is b[] when a is a valuetype, and
8574 * b is a reference type.
8577 if (eoclass->valuetype) {
8578 if ((eclass == mono_defaults.enum_class) ||
8579 (eclass == mono_defaults.enum_class->parent) ||
8580 (eclass == mono_defaults.object_class))
8584 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8586 /*FIXME properly handle nullables */
8587 /*FIXME properly handle (M)VAR */
8592 * mono_class_get_cctor:
8593 * @klass: A MonoClass pointer
8595 * Returns: The static constructor of @klass if it exists, NULL otherwise.
8598 mono_class_get_cctor (MonoClass *klass)
8600 MonoCachedClassInfo cached_info;
8602 if (image_is_dynamic (klass->image)) {
8604 * has_cctor is not set for these classes because mono_class_init () is
8607 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8610 if (!klass->has_cctor)
8613 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8615 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8616 if (!mono_error_ok (&error))
8617 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8621 if (mono_class_is_ginst (klass) && !klass->methods)
8622 return mono_class_get_inflated_method (klass, mono_class_get_cctor (mono_class_get_generic_class (klass)->container_class));
8624 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8628 * mono_class_get_finalizer:
8629 * @klass: The MonoClass pointer
8631 * Returns: The finalizer method of @klass if it exists, NULL otherwise.
8634 mono_class_get_finalizer (MonoClass *klass)
8636 MonoCachedClassInfo cached_info;
8639 mono_class_init (klass);
8640 if (!mono_class_has_finalizer (klass))
8643 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8645 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8646 if (!mono_error_ok (&error))
8647 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8650 mono_class_setup_vtable (klass);
8651 return klass->vtable [finalize_slot];
8656 * mono_class_needs_cctor_run:
8657 * @klass: the MonoClass pointer
8658 * @caller: a MonoMethod describing the caller
8660 * Determines whenever the class has a static constructor and whenever it
8661 * needs to be called when executing CALLER.
8664 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8668 method = mono_class_get_cctor (klass);
8670 return (method == caller) ? FALSE : TRUE;
8676 * mono_class_array_element_size:
8679 * Returns: The number of bytes an element of type @klass
8680 * uses when stored into an array.
8683 mono_class_array_element_size (MonoClass *klass)
8685 MonoType *type = &klass->byval_arg;
8688 switch (type->type) {
8691 case MONO_TYPE_BOOLEAN:
8695 case MONO_TYPE_CHAR:
8704 case MONO_TYPE_CLASS:
8705 case MONO_TYPE_STRING:
8706 case MONO_TYPE_OBJECT:
8707 case MONO_TYPE_SZARRAY:
8708 case MONO_TYPE_ARRAY:
8709 return sizeof (gpointer);
8714 case MONO_TYPE_VALUETYPE:
8715 if (type->data.klass->enumtype) {
8716 type = mono_class_enum_basetype (type->data.klass);
8717 klass = klass->element_class;
8720 return mono_class_instance_size (klass) - sizeof (MonoObject);
8721 case MONO_TYPE_GENERICINST:
8722 type = &type->data.generic_class->container_class->byval_arg;
8725 case MONO_TYPE_MVAR: {
8728 return mono_type_size (type, &align);
8730 case MONO_TYPE_VOID:
8734 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8740 * mono_array_element_size:
8741 * @ac: pointer to a #MonoArrayClass
8743 * Returns: The size of single array element.
8746 mono_array_element_size (MonoClass *ac)
8748 g_assert (ac->rank);
8749 return ac->sizes.element_size;
8753 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8754 MonoGenericContext *context)
8757 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8758 g_assert (mono_error_ok (&error));
8763 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8764 MonoGenericContext *context, MonoError *error)
8766 mono_error_init (error);
8768 if (image_is_dynamic (image)) {
8769 MonoClass *tmp_handle_class;
8770 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
8772 mono_error_assert_ok (error);
8773 g_assert (tmp_handle_class);
8775 *handle_class = tmp_handle_class;
8777 if (tmp_handle_class == mono_defaults.typehandle_class)
8778 return &((MonoClass*)obj)->byval_arg;
8783 switch (token & 0xff000000) {
8784 case MONO_TOKEN_TYPE_DEF:
8785 case MONO_TOKEN_TYPE_REF:
8786 case MONO_TOKEN_TYPE_SPEC: {
8789 *handle_class = mono_defaults.typehandle_class;
8790 type = mono_type_get_checked (image, token, context, error);
8794 mono_class_init (mono_class_from_mono_type (type));
8795 /* We return a MonoType* as handle */
8798 case MONO_TOKEN_FIELD_DEF: {
8800 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8802 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8806 *handle_class = mono_defaults.fieldhandle_class;
8807 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8811 mono_class_init (klass);
8812 return mono_class_get_field (klass, token);
8814 case MONO_TOKEN_METHOD_DEF:
8815 case MONO_TOKEN_METHOD_SPEC: {
8817 meth = mono_get_method_checked (image, token, NULL, context, error);
8819 *handle_class = mono_defaults.methodhandle_class;
8825 case MONO_TOKEN_MEMBER_REF: {
8826 guint32 cols [MONO_MEMBERREF_SIZE];
8828 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8829 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8830 mono_metadata_decode_blob_size (sig, &sig);
8831 if (*sig == 0x6) { /* it's a field */
8833 MonoClassField *field;
8834 field = mono_field_from_token_checked (image, token, &klass, context, error);
8836 *handle_class = mono_defaults.fieldhandle_class;
8840 meth = mono_get_method_checked (image, token, NULL, context, error);
8842 *handle_class = mono_defaults.methodhandle_class;
8847 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8853 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
8855 MonoClass *handle_class;
8856 mono_error_init (error);
8857 return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
8861 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
8863 return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
8866 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8869 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8871 get_cached_class_info = func;
8875 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8877 if (!get_cached_class_info)
8880 return get_cached_class_info (klass, res);
8884 mono_install_get_class_from_name (MonoGetClassFromName func)
8886 get_class_from_name = func;
8890 * mono_class_get_image:
8892 * Use this method to get the `MonoImage*` where this class came from.
8894 * Returns: The image where this class is defined.
8897 mono_class_get_image (MonoClass *klass)
8899 return klass->image;
8903 * mono_class_get_element_class:
8904 * @klass: the MonoClass to act on
8906 * Use this function to get the element class of an array.
8908 * Returns: The element class of an array.
8911 mono_class_get_element_class (MonoClass *klass)
8913 return klass->element_class;
8917 * mono_class_is_valuetype:
8918 * @klass: the MonoClass to act on
8920 * Use this method to determine if the provided `MonoClass*` represents a value type,
8921 * or a reference type.
8923 * Returns: TRUE if the MonoClass represents a ValueType, FALSE if it represents a reference type.
8926 mono_class_is_valuetype (MonoClass *klass)
8928 return klass->valuetype;
8932 * mono_class_is_enum:
8933 * @klass: the MonoClass to act on
8935 * Use this function to determine if the provided `MonoClass*` represents an enumeration.
8937 * Returns: TRUE if the MonoClass represents an enumeration.
8940 mono_class_is_enum (MonoClass *klass)
8942 return klass->enumtype;
8946 * mono_class_enum_basetype:
8947 * @klass: the MonoClass to act on
8949 * Use this function to get the underlying type for an enumeration value.
8951 * Returns: The underlying type representation for an enumeration.
8954 mono_class_enum_basetype (MonoClass *klass)
8956 if (klass->element_class == klass)
8957 /* SRE or broken types */
8960 return &klass->element_class->byval_arg;
8964 * mono_class_get_parent
8965 * @klass: the MonoClass to act on
8967 * Returns: The parent class for this class.
8970 mono_class_get_parent (MonoClass *klass)
8972 return klass->parent;
8976 * mono_class_get_nesting_type:
8977 * @klass: the MonoClass to act on
8979 * Use this function to obtain the class that the provided `MonoClass*` is nested on.
8981 * If the return is NULL, this indicates that this class is not nested.
8983 * Returns: The container type where this type is nested or NULL if this type is not a nested type.
8986 mono_class_get_nesting_type (MonoClass *klass)
8988 return klass->nested_in;
8992 * mono_class_get_rank:
8993 * @klass: the MonoClass to act on
8995 * Returns: The rank for the array (the number of dimensions).
8998 mono_class_get_rank (MonoClass *klass)
9004 * mono_class_get_name
9005 * @klass: the MonoClass to act on
9007 * Returns: The name of the class.
9010 mono_class_get_name (MonoClass *klass)
9016 * mono_class_get_namespace:
9017 * @klass: the MonoClass to act on
9019 * Returns: The namespace of the class.
9022 mono_class_get_namespace (MonoClass *klass)
9024 return klass->name_space;
9028 * mono_class_get_type:
9029 * @klass: the MonoClass to act on
9031 * This method returns the internal Type representation for the class.
9033 * Returns: The MonoType from the class.
9036 mono_class_get_type (MonoClass *klass)
9038 return &klass->byval_arg;
9042 * mono_class_get_type_token:
9043 * @klass: the MonoClass to act on
9045 * This method returns type token for the class.
9047 * Returns: The type token for the class.
9050 mono_class_get_type_token (MonoClass *klass)
9052 return klass->type_token;
9056 * mono_class_get_byref_type:
9057 * @klass: the MonoClass to act on
9062 mono_class_get_byref_type (MonoClass *klass)
9064 return &klass->this_arg;
9068 * mono_class_num_fields:
9069 * @klass: the MonoClass to act on
9071 * Returns: The number of static and instance fields in the class.
9074 mono_class_num_fields (MonoClass *klass)
9076 return klass->field.count;
9080 * mono_class_num_methods:
9081 * @klass: the MonoClass to act on
9083 * Returns: The number of methods in the class.
9086 mono_class_num_methods (MonoClass *klass)
9088 return klass->method.count;
9092 * mono_class_num_properties
9093 * @klass: the MonoClass to act on
9095 * Returns: The number of properties in the class.
9098 mono_class_num_properties (MonoClass *klass)
9100 mono_class_setup_properties (klass);
9102 return klass->ext->property.count;
9106 * mono_class_num_events:
9107 * @klass: the MonoClass to act on
9109 * Returns: The number of events in the class.
9112 mono_class_num_events (MonoClass *klass)
9114 mono_class_setup_events (klass);
9116 return klass->ext->event.count;
9120 * mono_class_get_fields:
9121 * @klass: the MonoClass to act on
9123 * This routine is an iterator routine for retrieving the fields in a class.
9125 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9126 * iterate over all of the elements. When no more values are
9127 * available, the return value is NULL.
9129 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
9132 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9134 MonoClassField* field;
9138 mono_class_setup_fields (klass);
9139 if (mono_class_has_failure (klass))
9141 /* start from the first */
9142 if (klass->field.count) {
9143 *iter = &klass->fields [0];
9144 return &klass->fields [0];
9150 field = (MonoClassField *)*iter;
9152 if (field < &klass->fields [klass->field.count]) {
9160 * mono_class_get_methods
9161 * @klass: the MonoClass to act on
9163 * This routine is an iterator routine for retrieving the fields in a class.
9165 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9166 * iterate over all of the elements. When no more values are
9167 * available, the return value is NULL.
9169 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
9172 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9174 MonoMethod** method;
9178 mono_class_setup_methods (klass);
9181 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9182 * FIXME we should better report this error to the caller
9184 if (!klass->methods)
9186 /* start from the first */
9187 if (klass->method.count) {
9188 *iter = &klass->methods [0];
9189 return klass->methods [0];
9195 method = (MonoMethod **)*iter;
9197 if (method < &klass->methods [klass->method.count]) {
9205 * mono_class_get_virtual_methods:
9207 * Iterate over the virtual methods of KLASS.
9209 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9212 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9214 MonoMethod** method;
9217 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9219 mono_class_setup_methods (klass);
9221 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9222 * FIXME we should better report this error to the caller
9224 if (!klass->methods)
9226 /* start from the first */
9227 method = &klass->methods [0];
9229 method = (MonoMethod **)*iter;
9232 while (method < &klass->methods [klass->method.count]) {
9233 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9237 if (method < &klass->methods [klass->method.count]) {
9244 /* Search directly in metadata to avoid calling setup_methods () */
9245 MonoMethod *res = NULL;
9251 start_index = GPOINTER_TO_UINT (*iter);
9254 int first_idx = mono_class_get_first_method_idx (klass);
9255 for (i = start_index; i < klass->method.count; ++i) {
9258 /* first_idx points into the methodptr table */
9259 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
9261 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9265 if (i < klass->method.count) {
9267 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9268 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9270 /* Add 1 here so the if (*iter) check fails */
9271 *iter = GUINT_TO_POINTER (i + 1);
9280 * mono_class_get_properties:
9281 * @klass: the MonoClass to act on
9283 * This routine is an iterator routine for retrieving the properties in a class.
9285 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9286 * iterate over all of the elements. When no more values are
9287 * available, the return value is NULL.
9289 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9292 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9294 MonoProperty* property;
9298 mono_class_setup_properties (klass);
9299 /* start from the first */
9300 if (klass->ext->property.count) {
9301 *iter = &klass->ext->properties [0];
9302 return (MonoProperty *)*iter;
9308 property = (MonoProperty *)*iter;
9310 if (property < &klass->ext->properties [klass->ext->property.count]) {
9312 return (MonoProperty *)*iter;
9318 * mono_class_get_events:
9319 * @klass: the MonoClass to act on
9321 * This routine is an iterator routine for retrieving the properties in a class.
9323 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9324 * iterate over all of the elements. When no more values are
9325 * available, the return value is NULL.
9327 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9330 mono_class_get_events (MonoClass* klass, gpointer *iter)
9336 mono_class_setup_events (klass);
9337 /* start from the first */
9338 if (klass->ext->event.count) {
9339 *iter = &klass->ext->events [0];
9340 return (MonoEvent *)*iter;
9346 event = (MonoEvent *)*iter;
9348 if (event < &klass->ext->events [klass->ext->event.count]) {
9350 return (MonoEvent *)*iter;
9356 * mono_class_get_interfaces
9357 * @klass: the MonoClass to act on
9359 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9361 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9362 * iterate over all of the elements. When no more values are
9363 * available, the return value is NULL.
9365 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9368 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9376 mono_class_init (klass);
9377 if (!klass->interfaces_inited) {
9378 mono_class_setup_interfaces (klass, &error);
9379 if (!mono_error_ok (&error)) {
9380 mono_error_cleanup (&error);
9384 /* start from the first */
9385 if (klass->interface_count) {
9386 *iter = &klass->interfaces [0];
9387 return klass->interfaces [0];
9393 iface = (MonoClass **)*iter;
9395 if (iface < &klass->interfaces [klass->interface_count]) {
9403 setup_nested_types (MonoClass *klass)
9406 GList *classes, *nested_classes, *l;
9409 if (klass->nested_classes_inited)
9412 if (!klass->type_token)
9413 klass->nested_classes_inited = TRUE;
9415 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9419 guint32 cols [MONO_NESTED_CLASS_SIZE];
9420 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9421 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9422 if (!mono_error_ok (&error)) {
9423 /*FIXME don't swallow the error message*/
9424 mono_error_cleanup (&error);
9426 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9430 classes = g_list_prepend (classes, nclass);
9432 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9435 mono_class_alloc_ext (klass);
9437 nested_classes = NULL;
9438 for (l = classes; l; l = l->next)
9439 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9440 g_list_free (classes);
9442 mono_image_lock (klass->image);
9444 mono_memory_barrier ();
9445 if (!klass->nested_classes_inited) {
9446 klass->ext->nested_classes = nested_classes;
9447 mono_memory_barrier ();
9448 klass->nested_classes_inited = TRUE;
9451 mono_image_unlock (klass->image);
9455 * mono_class_get_nested_types
9456 * @klass: the MonoClass to act on
9458 * This routine is an iterator routine for retrieving the nested types of a class.
9459 * This works only if @klass is non-generic, or a generic type definition.
9461 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9462 * iterate over all of the elements. When no more values are
9463 * available, the return value is NULL.
9465 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9468 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9474 if (!klass->nested_classes_inited)
9475 setup_nested_types (klass);
9478 /* start from the first */
9479 if (klass->ext && klass->ext->nested_classes) {
9480 *iter = klass->ext->nested_classes;
9481 return (MonoClass *)klass->ext->nested_classes->data;
9483 /* no nested types */
9487 item = (GList *)*iter;
9491 return (MonoClass *)item->data;
9498 * mono_class_is_delegate
9499 * @klass: the MonoClass to act on
9501 * Returns: TRUE if the MonoClass represents a System.Delegate.
9504 mono_class_is_delegate (MonoClass *klass)
9506 return klass->delegate;
9510 * mono_class_implements_interface
9511 * @klass: The MonoClass to act on
9512 * @interface: The interface to check if @klass implements.
9514 * Returns: TRUE if @klass implements @interface.
9517 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9519 return mono_class_is_assignable_from (iface, klass);
9523 * mono_field_get_name:
9524 * @field: the MonoClassField to act on
9526 * Returns: The name of the field.
9529 mono_field_get_name (MonoClassField *field)
9535 * mono_field_get_type:
9536 * @field: the MonoClassField to act on
9538 * Returns: MonoType of the field.
9541 mono_field_get_type (MonoClassField *field)
9544 MonoType *type = mono_field_get_type_checked (field, &error);
9545 if (!mono_error_ok (&error)) {
9546 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9547 mono_error_cleanup (&error);
9554 * mono_field_get_type_checked:
9555 * @field: the MonoClassField to act on
9556 * @error: used to return any erro found while retrieving @field type
9558 * Returns: MonoType of the field.
9561 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9563 mono_error_init (error);
9565 mono_field_resolve_type (field, error);
9570 * mono_field_get_parent:
9571 * @field: the MonoClassField to act on
9573 * Returns: MonoClass where the field was defined.
9576 mono_field_get_parent (MonoClassField *field)
9578 return field->parent;
9582 * mono_field_get_flags;
9583 * @field: the MonoClassField to act on
9585 * The metadata flags for a field are encoded using the
9586 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9588 * Returns: The flags for the field.
9591 mono_field_get_flags (MonoClassField *field)
9594 return mono_field_resolve_flags (field);
9595 return field->type->attrs;
9599 * mono_field_get_offset:
9600 * @field: the MonoClassField to act on
9602 * Returns: The field offset.
9605 mono_field_get_offset (MonoClassField *field)
9607 return field->offset;
9611 mono_field_get_rva (MonoClassField *field)
9615 MonoClass *klass = field->parent;
9616 MonoFieldDefaultValue *field_def_values;
9618 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9620 if (!klass->ext || !klass->ext->field_def_values) {
9621 mono_class_alloc_ext (klass);
9623 field_def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9625 mono_image_lock (klass->image);
9626 if (!klass->ext->field_def_values)
9627 klass->ext->field_def_values = field_def_values;
9628 mono_image_unlock (klass->image);
9631 field_index = mono_field_get_index (field);
9633 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9634 int first_field_idx = mono_class_get_first_field_idx (klass);
9635 mono_metadata_field_info (field->parent->image, first_field_idx + field_index, NULL, &rva, NULL);
9637 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9638 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9641 return klass->ext->field_def_values [field_index].data;
9645 * mono_field_get_data:
9646 * @field: the MonoClassField to act on
9648 * Returns: A pointer to the metadata constant value or to the field
9649 * data if it has an RVA flag.
9652 mono_field_get_data (MonoClassField *field)
9654 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9655 MonoTypeEnum def_type;
9657 return mono_class_get_field_default_value (field, &def_type);
9658 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9659 return mono_field_get_rva (field);
9666 * mono_property_get_name:
9667 * @prop: the MonoProperty to act on
9669 * Returns: The name of the property
9672 mono_property_get_name (MonoProperty *prop)
9678 * mono_property_get_set_method
9679 * @prop: the MonoProperty to act on.
9681 * Returns: The setter method of the property (A MonoMethod)
9684 mono_property_get_set_method (MonoProperty *prop)
9690 * mono_property_get_get_method
9691 * @prop: the MonoProperty to act on.
9693 * Returns: The setter method of the property (A MonoMethod)
9696 mono_property_get_get_method (MonoProperty *prop)
9702 * mono_property_get_parent:
9703 * @prop: the MonoProperty to act on.
9705 * Returns: The MonoClass where the property was defined.
9708 mono_property_get_parent (MonoProperty *prop)
9710 return prop->parent;
9714 * mono_property_get_flags:
9715 * @prop: the MonoProperty to act on.
9717 * The metadata flags for a property are encoded using the
9718 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9720 * Returns: The flags for the property.
9723 mono_property_get_flags (MonoProperty *prop)
9729 * mono_event_get_name:
9730 * @event: the MonoEvent to act on
9732 * Returns: The name of the event.
9735 mono_event_get_name (MonoEvent *event)
9741 * mono_event_get_add_method:
9742 * @event: The MonoEvent to act on.
9744 * Returns: The @add' method for the event (a MonoMethod).
9747 mono_event_get_add_method (MonoEvent *event)
9753 * mono_event_get_remove_method:
9754 * @event: The MonoEvent to act on.
9756 * Returns: The @remove method for the event (a MonoMethod).
9759 mono_event_get_remove_method (MonoEvent *event)
9761 return event->remove;
9765 * mono_event_get_raise_method:
9766 * @event: The MonoEvent to act on.
9768 * Returns: The @raise method for the event (a MonoMethod).
9771 mono_event_get_raise_method (MonoEvent *event)
9773 return event->raise;
9777 * mono_event_get_parent:
9778 * @event: the MonoEvent to act on.
9780 * Returns: The MonoClass where the event is defined.
9783 mono_event_get_parent (MonoEvent *event)
9785 return event->parent;
9789 * mono_event_get_flags
9790 * @event: the MonoEvent to act on.
9792 * The metadata flags for an event are encoded using the
9793 * EVENT_* constants. See the tabledefs.h file for details.
9795 * Returns: The flags for the event.
9798 mono_event_get_flags (MonoEvent *event)
9800 return event->attrs;
9804 * mono_class_get_method_from_name:
9805 * @klass: where to look for the method
9806 * @name: name of the method
9807 * @param_count: number of parameters. -1 for any number.
9809 * Obtains a MonoMethod with a given name and number of parameters.
9810 * It only works if there are no multiple signatures for any given method name.
9813 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9815 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9819 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9821 MonoMethod *res = NULL;
9824 /* Search directly in the metadata to avoid calling setup_methods () */
9825 int first_idx = mono_class_get_first_method_idx (klass);
9826 for (i = 0; i < klass->method.count; ++i) {
9828 guint32 cols [MONO_METHOD_SIZE];
9830 MonoMethodSignature *sig;
9832 /* first_idx points into the methodptr table */
9833 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, first_idx + i, cols, MONO_METHOD_SIZE);
9835 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9836 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9838 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9841 if (param_count == -1) {
9845 sig = mono_method_signature_checked (method, &error);
9847 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9850 if (sig->param_count == param_count) {
9861 * mono_class_get_method_from_name_flags:
9862 * @klass: where to look for the method
9863 * @name_space: name of the method
9864 * @param_count: number of parameters. -1 for any number.
9865 * @flags: flags which must be set in the method
9867 * Obtains a MonoMethod with a given name and number of parameters.
9868 * It only works if there are no multiple signatures for any given method name.
9871 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9873 MonoMethod *res = NULL;
9876 mono_class_init (klass);
9878 if (mono_class_is_ginst (klass) && !klass->methods) {
9879 res = mono_class_get_method_from_name_flags (mono_class_get_generic_class (klass)->container_class, name, param_count, flags);
9882 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9883 if (!mono_error_ok (&error))
9884 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9889 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9890 mono_class_setup_methods (klass);
9892 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9893 See mono/tests/array_load_exception.il
9894 FIXME we should better report this error to the caller
9896 if (!klass->methods)
9898 for (i = 0; i < klass->method.count; ++i) {
9899 MonoMethod *method = klass->methods [i];
9901 if (method->name[0] == name [0] &&
9902 !strcmp (name, method->name) &&
9903 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9904 ((method->flags & flags) == flags)) {
9911 res = find_method_in_metadata (klass, name, param_count, flags);
9918 * mono_class_set_failure:
9919 * @klass: class in which the failure was detected
9920 * @ex_type: the kind of exception/error to be thrown (later)
9921 * @ex_data: exception data (specific to each type of exception/error)
9923 * Keep a detected failure informations in the class for later processing.
9924 * Note that only the first failure is kept.
9926 * LOCKING: Acquires the loader lock.
9929 mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error)
9931 g_assert (boxed_error != NULL);
9933 if (mono_class_has_failure (klass))
9936 mono_loader_lock ();
9937 klass->has_failure = 1;
9938 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, boxed_error);
9939 mono_loader_unlock ();
9945 mono_class_has_failure (const MonoClass *klass)
9947 g_assert (klass != NULL);
9948 return klass->has_failure != 0;
9953 * mono_class_set_type_load_failure:
9954 * @klass: class in which the failure was detected
9955 * @fmt: Printf-style error message string.
9957 * Collect detected failure informaion in the class for later processing.
9958 * The error is stored as a MonoErrorBoxed as with mono_error_set_type_load_class ()
9959 * Note that only the first failure is kept.
9961 * Returns FALSE if a failure was already set on the class, or TRUE otherwise.
9963 * LOCKING: Acquires the loader lock.
9966 mono_class_set_type_load_failure (MonoClass *klass, const char * fmt, ...)
9968 MonoError prepare_error;
9971 if (mono_class_has_failure (klass))
9974 mono_error_init (&prepare_error);
9976 va_start (args, fmt);
9977 mono_error_vset_type_load_class (&prepare_error, klass, fmt, args);
9980 MonoErrorBoxed *box = mono_error_box (&prepare_error, klass->image);
9981 mono_error_cleanup (&prepare_error);
9982 return mono_class_set_failure (klass, box);
9986 * mono_class_get_exception_data:
9988 * Return the exception_data property of KLASS.
9990 * LOCKING: Acquires the loader lock.
9993 mono_class_get_exception_data (const MonoClass *klass)
9995 return mono_image_property_lookup (klass->image, (MonoClass*)klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9999 * mono_classes_init:
10001 * Initialize the resources used by this module.
10004 mono_classes_init (void)
10006 mono_os_mutex_init (&classes_mutex);
10008 mono_native_tls_alloc (&setup_fields_tls_id, NULL);
10009 mono_native_tls_alloc (&init_pending_tls_id, NULL);
10011 mono_counters_register ("MonoClassDef count",
10012 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_def_count);
10013 mono_counters_register ("MonoClassGtd count",
10014 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gtd_count);
10015 mono_counters_register ("MonoClassGenericInst count",
10016 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ginst_count);
10017 mono_counters_register ("MonoClassGenericParam count",
10018 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gparam_count);
10019 mono_counters_register ("MonoClassArray count",
10020 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_array_count);
10021 mono_counters_register ("MonoClassPointer count",
10022 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_pointer_count);
10023 mono_counters_register ("Inflated methods size",
10024 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
10025 mono_counters_register ("Inflated classes size",
10026 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
10027 mono_counters_register ("MonoClass size",
10028 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
10029 mono_counters_register ("MonoClassExt size",
10030 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
10032 mono_counters_register ("MonoClassExt count",
10033 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_count);
10037 * mono_classes_cleanup:
10039 * Free the resources used by this module.
10042 mono_classes_cleanup (void)
10044 mono_native_tls_free (setup_fields_tls_id);
10045 mono_native_tls_free (init_pending_tls_id);
10047 if (global_interface_bitset)
10048 mono_bitset_free (global_interface_bitset);
10049 global_interface_bitset = NULL;
10050 mono_os_mutex_destroy (&classes_mutex);
10054 * mono_class_get_exception_for_failure:
10055 * @klass: class in which the failure was detected
10057 * Return a constructed MonoException than the caller can then throw
10058 * using mono_raise_exception - or NULL if no failure is present (or
10059 * doesn't result in an exception).
10062 mono_class_get_exception_for_failure (MonoClass *klass)
10064 if (!mono_class_has_failure (klass))
10066 MonoError unboxed_error;
10067 mono_error_init (&unboxed_error);
10068 mono_error_set_for_class_failure (&unboxed_error, klass);
10069 return mono_error_convert_to_exception (&unboxed_error);
10073 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
10075 outer_klass = mono_class_get_generic_type_definition (outer_klass);
10076 inner_klass = mono_class_get_generic_type_definition (inner_klass);
10078 if (outer_klass == inner_klass)
10080 inner_klass = inner_klass->nested_in;
10081 } while (inner_klass);
10086 mono_class_get_generic_type_definition (MonoClass *klass)
10088 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
10089 return gklass ? gklass->container_class : klass;
10093 * Check if @klass is a subtype of @parent ignoring generic instantiations.
10095 * Generic instantiations are ignored for all super types of @klass.
10097 * Visibility checks ignoring generic instantiations.
10100 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
10103 klass = mono_class_get_generic_type_definition (klass);
10104 parent = mono_class_get_generic_type_definition (parent);
10105 mono_class_setup_supertypes (klass);
10107 for (i = 0; i < klass->idepth; ++i) {
10108 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
10114 * Subtype can only access parent members with family protection if the site object
10115 * is subclass of Subtype. For example:
10116 * class A { protected int x; }
10118 * void valid_access () {
10122 * void invalid_access () {
10129 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
10131 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
10134 if (context_klass == NULL)
10136 /*if access_klass is not member_klass context_klass must be type compat*/
10137 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10143 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10146 if (accessing == accessed)
10148 if (!accessed || !accessing)
10151 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10152 * anywhere so untrusted friends are not safe to access platform's code internals */
10153 if (mono_security_core_clr_enabled ()) {
10154 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10158 mono_assembly_load_friends (accessed);
10159 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10160 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10161 /* Be conservative with checks */
10162 if (!friend_->name)
10164 if (strcmp (accessing->aname.name, friend_->name))
10166 if (friend_->public_key_token [0]) {
10167 if (!accessing->aname.public_key_token [0])
10169 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10178 * If klass is a generic type or if it is derived from a generic type, return the
10179 * MonoClass of the generic definition
10180 * Returns NULL if not found
10183 get_generic_definition_class (MonoClass *klass)
10186 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
10187 if (gklass && gklass->container_class)
10188 return gklass->container_class;
10189 klass = klass->parent;
10195 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10198 for (i = 0; i < ginst->type_argc; ++i) {
10199 MonoType *type = ginst->type_argv[i];
10200 switch (type->type) {
10201 case MONO_TYPE_SZARRAY:
10202 if (!can_access_type (access_klass, type->data.klass))
10205 case MONO_TYPE_ARRAY:
10206 if (!can_access_type (access_klass, type->data.array->eklass))
10209 case MONO_TYPE_PTR:
10210 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10213 case MONO_TYPE_CLASS:
10214 case MONO_TYPE_VALUETYPE:
10215 case MONO_TYPE_GENERICINST:
10216 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10226 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10230 if (access_klass == member_klass)
10233 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10236 if (access_klass->element_class && !access_klass->enumtype)
10237 access_klass = access_klass->element_class;
10239 if (member_klass->element_class && !member_klass->enumtype)
10240 member_klass = member_klass->element_class;
10242 access_level = mono_class_get_flags (member_klass) & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10244 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10247 if (mono_class_is_ginst (member_klass) && !can_access_instantiation (access_klass, mono_class_get_generic_class (member_klass)->context.class_inst))
10250 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10253 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10256 /*Non nested type with nested visibility. We just fail it.*/
10257 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10260 switch (access_level) {
10261 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10262 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10264 case TYPE_ATTRIBUTE_PUBLIC:
10267 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10270 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10271 return is_nesting_type (member_klass, access_klass);
10273 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10274 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10276 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10277 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10279 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10280 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10281 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10283 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10284 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10285 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10290 /* FIXME: check visibility of type, too */
10292 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10294 MonoClass *member_generic_def;
10295 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10298 MonoGenericClass *access_gklass = mono_class_try_get_generic_class (access_klass);
10299 if (((access_gklass && access_gklass->container_class) ||
10300 mono_class_is_gtd (access_klass)) &&
10301 (member_generic_def = get_generic_definition_class (member_klass))) {
10302 MonoClass *access_container;
10304 if (mono_class_is_gtd (access_klass))
10305 access_container = access_klass;
10307 access_container = access_gklass->container_class;
10309 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10313 /* Partition I 8.5.3.2 */
10314 /* the access level values are the same for fields and methods */
10315 switch (access_level) {
10316 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10317 /* same compilation unit */
10318 return access_klass->image == member_klass->image;
10319 case FIELD_ATTRIBUTE_PRIVATE:
10320 return access_klass == member_klass;
10321 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10322 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10323 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10326 case FIELD_ATTRIBUTE_ASSEMBLY:
10327 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10328 case FIELD_ATTRIBUTE_FAMILY:
10329 if (is_valid_family_access (access_klass, member_klass, context_klass))
10332 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10333 if (is_valid_family_access (access_klass, member_klass, context_klass))
10335 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10336 case FIELD_ATTRIBUTE_PUBLIC:
10343 * mono_method_can_access_field:
10344 * @method: Method that will attempt to access the field
10345 * @field: the field to access
10347 * Used to determine if a method is allowed to access the specified field.
10349 * Returns: TRUE if the given @method is allowed to access the @field while following
10350 * the accessibility rules of the CLI.
10353 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10355 /* FIXME: check all overlapping fields */
10356 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10358 MonoClass *nested = method->klass->nested_in;
10360 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10363 nested = nested->nested_in;
10370 * mono_method_can_access_method:
10371 * @method: Method that will attempt to access the other method
10372 * @called: the method that we want to probe for accessibility.
10374 * Used to determine if the @method is allowed to access the specified @called method.
10376 * Returns: TRUE if the given @method is allowed to invoke the @called while following
10377 * the accessibility rules of the CLI.
10380 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10382 method = mono_method_get_method_definition (method);
10383 called = mono_method_get_method_definition (called);
10384 return mono_method_can_access_method_full (method, called, NULL);
10388 * mono_method_can_access_method_full:
10389 * @method: The caller method
10390 * @called: The called method
10391 * @context_klass: The static type on stack of the owner @called object used
10393 * This function must be used with instance calls, as they have more strict family accessibility.
10394 * It can be used with static methods, but context_klass should be NULL.
10396 * Returns: TRUE if caller have proper visibility and acessibility to @called
10399 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10401 /* Wrappers are except from access checks */
10402 if (method->wrapper_type != MONO_WRAPPER_NONE || called->wrapper_type != MONO_WRAPPER_NONE)
10405 MonoClass *access_class = method->klass;
10406 MonoClass *member_class = called->klass;
10407 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10409 MonoClass *nested = access_class->nested_in;
10411 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10414 nested = nested->nested_in;
10421 can = can_access_type (access_class, member_class);
10423 MonoClass *nested = access_class->nested_in;
10425 can = can_access_type (nested, member_class);
10428 nested = nested->nested_in;
10435 if (called->is_inflated) {
10436 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10437 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10446 * mono_method_can_access_field_full:
10447 * @method: The caller method
10448 * @field: The accessed field
10449 * @context_klass: The static type on stack of the owner @field object used
10451 * This function must be used with instance fields, as they have more strict family accessibility.
10452 * It can be used with static fields, but context_klass should be NULL.
10454 * Returns: TRUE if caller have proper visibility and acessibility to @field
10457 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10459 MonoClass *access_class = method->klass;
10460 MonoClass *member_class = field->parent;
10461 /* FIXME: check all overlapping fields */
10462 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10464 MonoClass *nested = access_class->nested_in;
10466 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10469 nested = nested->nested_in;
10476 can = can_access_type (access_class, member_class);
10478 MonoClass *nested = access_class->nested_in;
10480 can = can_access_type (nested, member_class);
10483 nested = nested->nested_in;
10493 * mono_class_can_access_class:
10494 * @source_class: The source class
10495 * @target_class: The accessed class
10497 * This function returns is @target_class is visible to @source_class
10499 * Returns: TRUE if source have proper visibility and acessibility to target
10502 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10504 return can_access_type (source_class, target_class);
10508 * mono_type_is_valid_enum_basetype:
10509 * @type: The MonoType to check
10511 * Returns: TRUE if the type can be used as the basetype of an enum
10513 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10514 switch (type->type) {
10517 case MONO_TYPE_BOOLEAN:
10520 case MONO_TYPE_CHAR:
10534 * mono_class_is_valid_enum:
10535 * @klass: An enum class to be validated
10537 * This method verify the required properties an enum should have.
10539 * Returns: TRUE if the informed enum class is valid
10541 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10542 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10543 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10546 mono_class_is_valid_enum (MonoClass *klass)
10548 MonoClassField * field;
10549 gpointer iter = NULL;
10550 gboolean found_base_field = FALSE;
10552 g_assert (klass->enumtype);
10553 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10554 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10558 if (!mono_class_is_auto_layout (klass))
10561 while ((field = mono_class_get_fields (klass, &iter))) {
10562 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10563 if (found_base_field)
10565 found_base_field = TRUE;
10566 if (!mono_type_is_valid_enum_basetype (field->type))
10571 if (!found_base_field)
10574 if (klass->method.count > 0)
10581 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10583 return gklass->context.class_inst == mono_class_get_generic_container (gklass->container_class)->context.class_inst;
10587 * mono_class_setup_interface_id:
10589 * Initializes MonoClass::interface_id if required.
10591 * LOCKING: Acquires the loader lock.
10594 mono_class_setup_interface_id (MonoClass *klass)
10596 mono_loader_lock ();
10597 if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10598 klass->interface_id = mono_get_unique_iid (klass);
10599 mono_loader_unlock ();
10603 * mono_class_alloc_ext:
10605 * Allocate klass->ext if not already done.
10608 mono_class_alloc_ext (MonoClass *klass)
10615 ext = (MonoClassExt *)mono_class_alloc0 (klass, sizeof (MonoClassExt));
10616 mono_image_lock (klass->image);
10617 mono_memory_barrier ();
10620 class_ext_size += sizeof (MonoClassExt);
10622 mono_image_unlock (klass->image);
10626 * mono_class_setup_interfaces:
10628 * Initialize klass->interfaces/interfaces_count.
10629 * LOCKING: Acquires the loader lock.
10630 * This function can fail the type.
10633 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10635 int i, interface_count;
10636 MonoClass **interfaces;
10638 mono_error_init (error);
10640 if (klass->interfaces_inited)
10643 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10644 MonoType *args [1];
10646 /* generic IList, ICollection, IEnumerable */
10647 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10648 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10650 args [0] = &klass->element_class->byval_arg;
10651 interfaces [0] = mono_class_bind_generic_parameters (
10652 mono_defaults.generic_ilist_class, 1, args, FALSE);
10653 if (interface_count > 1)
10654 interfaces [1] = mono_class_bind_generic_parameters (
10655 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10656 } else if (mono_class_is_ginst (klass)) {
10657 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
10659 mono_class_setup_interfaces (gklass, error);
10660 if (!mono_error_ok (error)) {
10661 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10665 interface_count = gklass->interface_count;
10666 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10667 for (i = 0; i < interface_count; i++) {
10668 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (mono_class_get_generic_class (klass)), error);
10669 if (!mono_error_ok (error)) {
10670 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10675 interface_count = 0;
10679 mono_image_lock (klass->image);
10681 if (!klass->interfaces_inited) {
10682 klass->interface_count = interface_count;
10683 klass->interfaces = interfaces;
10685 mono_memory_barrier ();
10687 klass->interfaces_inited = TRUE;
10690 mono_image_unlock (klass->image);
10694 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10696 MonoClass *klass = field->parent;
10697 MonoImage *image = klass->image;
10698 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10699 int field_idx = field - klass->fields;
10701 mono_error_init (error);
10704 MonoClassField *gfield = >d->fields [field_idx];
10705 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10706 if (!mono_error_ok (error)) {
10707 char *full_name = mono_type_get_full_name (gtd);
10708 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));
10709 g_free (full_name);
10712 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10713 if (!mono_error_ok (error)) {
10714 char *full_name = mono_type_get_full_name (klass);
10715 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));
10716 g_free (full_name);
10720 guint32 cols [MONO_FIELD_SIZE];
10721 MonoGenericContainer *container = NULL;
10722 int idx = mono_class_get_first_field_idx (klass) + field_idx;
10724 /*FIXME, in theory we do not lazy load SRE fields*/
10725 g_assert (!image_is_dynamic (image));
10727 if (mono_class_is_gtd (klass)) {
10728 container = mono_class_get_generic_container (klass);
10730 container = mono_class_get_generic_container (gtd);
10731 g_assert (container);
10734 /* first_field_idx and idx points into the fieldptr table */
10735 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10737 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10738 char *full_name = mono_type_get_full_name (klass);
10739 mono_error_set_type_load_class (error, klass, "Could not verify field '%s:%s' signature", full_name, field->name);;
10740 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
10741 g_free (full_name);
10745 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10747 mono_metadata_decode_value (sig, &sig);
10748 /* FIELD signature == 0x06 */
10749 g_assert (*sig == 0x06);
10751 field->type = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10752 if (!field->type) {
10753 char *full_name = mono_type_get_full_name (klass);
10754 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));
10755 g_free (full_name);
10761 mono_field_resolve_flags (MonoClassField *field)
10763 MonoClass *klass = field->parent;
10764 MonoImage *image = klass->image;
10765 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10766 int field_idx = field - klass->fields;
10770 MonoClassField *gfield = >d->fields [field_idx];
10771 return mono_field_get_flags (gfield);
10773 int idx = mono_class_get_first_field_idx (klass) + field_idx;
10775 /*FIXME, in theory we do not lazy load SRE fields*/
10776 g_assert (!image_is_dynamic (image));
10778 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10783 * mono_class_get_fields_lazy:
10784 * @klass: the MonoClass to act on
10786 * This routine is an iterator routine for retrieving the fields in a class.
10787 * Only minimal information about fields are loaded. Accessors must be used
10788 * for all MonoClassField returned.
10790 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10791 * iterate over all of the elements. When no more values are
10792 * available, the return value is NULL.
10794 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10797 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10799 MonoClassField* field;
10803 mono_class_setup_basic_field_info (klass);
10804 if (!klass->fields)
10806 /* start from the first */
10807 if (klass->field.count) {
10808 *iter = &klass->fields [0];
10809 return (MonoClassField *)*iter;
10815 field = (MonoClassField *)*iter;
10817 if (field < &klass->fields [klass->field.count]) {
10819 return (MonoClassField *)*iter;
10825 mono_class_full_name (MonoClass *klass)
10827 return mono_type_full_name (&klass->byval_arg);
10830 /* Declare all shared lazy type lookup functions */
10831 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, System.Runtime.InteropServices, SafeHandle)