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 /* I've confirmed iids safe past 16 bits, however bitset code uses a signed int while testing.
2884 * Once this changes, it should be safe for us to allow 2^32-1 interfaces, until then 2^31-2 is the max. */
2885 g_assert (iid < INT_MAX);
2890 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2895 mono_class_setup_interfaces (klass, error);
2896 return_if_nok (error);
2898 for (i = 0; i < klass->interface_count; i++) {
2899 ic = klass->interfaces [i];
2902 *res = g_ptr_array_new ();
2903 g_ptr_array_add (*res, ic);
2904 mono_class_init (ic);
2905 if (mono_class_has_failure (ic)) {
2906 mono_error_set_type_load_class (error, ic, "Error Loading class");
2910 collect_implemented_interfaces_aux (ic, res, error);
2911 return_if_nok (error);
2916 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2918 GPtrArray *res = NULL;
2920 collect_implemented_interfaces_aux (klass, &res, error);
2921 if (!mono_error_ok (error)) {
2923 g_ptr_array_free (res, TRUE);
2930 compare_interface_ids (const void *p_key, const void *p_element) {
2931 const MonoClass *key = (const MonoClass *)p_key;
2932 const MonoClass *element = *(const MonoClass **)p_element;
2934 return (key->interface_id - element->interface_id);
2937 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2939 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2940 MonoClass **result = (MonoClass **)mono_binary_search (
2942 klass->interfaces_packed,
2943 klass->interface_offsets_count,
2944 sizeof (MonoClass *),
2945 compare_interface_ids);
2947 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2954 * mono_class_interface_offset_with_variance:
2956 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2957 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2959 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2961 * FIXME figure out MS disambiguation rules and fix this function.
2964 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2965 int i = mono_class_interface_offset (klass, itf);
2966 *non_exact_match = FALSE;
2970 if (!mono_class_has_variant_generic_params (itf))
2973 for (i = 0; i < klass->interface_offsets_count; i++) {
2974 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2975 *non_exact_match = TRUE;
2976 return klass->interface_offsets_packed [i];
2984 print_implemented_interfaces (MonoClass *klass) {
2987 GPtrArray *ifaces = NULL;
2989 int ancestor_level = 0;
2991 name = mono_type_get_full_name (klass);
2992 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2995 for (i = 0; i < klass->interface_offsets_count; i++)
2996 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2997 klass->interfaces_packed [i]->interface_id,
2998 klass->interface_offsets_packed [i],
2999 klass->interfaces_packed [i]->method.count,
3000 klass->interfaces_packed [i]->name_space,
3001 klass->interfaces_packed [i]->name );
3002 printf ("Interface flags: ");
3003 for (i = 0; i <= klass->max_interface_id; i++)
3004 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
3005 printf ("(%d,T)", i);
3007 printf ("(%d,F)", i);
3009 printf ("Dump interface flags:");
3010 #ifdef COMPRESSED_INTERFACE_BITMAP
3012 const uint8_t* p = klass->interface_bitmap;
3013 i = klass->max_interface_id;
3015 printf (" %d x 00 %02X", p [0], p [1]);
3021 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
3022 printf (" %02X", klass->interface_bitmap [i]);
3025 while (klass != NULL) {
3026 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
3027 ifaces = mono_class_get_implemented_interfaces (klass, &error);
3028 if (!mono_error_ok (&error)) {
3029 printf (" Type failed due to %s\n", mono_error_get_message (&error));
3030 mono_error_cleanup (&error);
3031 } else if (ifaces) {
3032 for (i = 0; i < ifaces->len; i++) {
3033 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3034 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
3035 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3037 mono_class_interface_offset (klass, ic),
3042 g_ptr_array_free (ifaces, TRUE);
3045 klass = klass->parent;
3050 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
3053 args [0] = &arg0->byval_arg;
3055 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
3059 array_class_get_if_rank (MonoClass *klass, guint rank)
3061 return rank ? mono_array_class_get (klass, rank) : klass;
3065 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
3067 valuetype_types [0] = eclass;
3068 if (eclass == mono_defaults.int16_class)
3069 valuetype_types [1] = mono_defaults.uint16_class;
3070 else if (eclass == mono_defaults.uint16_class)
3071 valuetype_types [1] = mono_defaults.int16_class;
3072 else if (eclass == mono_defaults.int32_class)
3073 valuetype_types [1] = mono_defaults.uint32_class;
3074 else if (eclass == mono_defaults.uint32_class)
3075 valuetype_types [1] = mono_defaults.int32_class;
3076 else if (eclass == mono_defaults.int64_class)
3077 valuetype_types [1] = mono_defaults.uint64_class;
3078 else if (eclass == mono_defaults.uint64_class)
3079 valuetype_types [1] = mono_defaults.int64_class;
3080 else if (eclass == mono_defaults.byte_class)
3081 valuetype_types [1] = mono_defaults.sbyte_class;
3082 else if (eclass == mono_defaults.sbyte_class)
3083 valuetype_types [1] = mono_defaults.byte_class;
3084 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
3085 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
3088 static GENERATE_GET_CLASS_WITH_CACHE (generic_icollection, System.Collections.Generic, ICollection`1)
3089 static GENERATE_GET_CLASS_WITH_CACHE (generic_ienumerable, System.Collections.Generic, IEnumerable`1)
3090 static GENERATE_GET_CLASS_WITH_CACHE (generic_ienumerator, System.Collections.Generic, IEnumerator`1)
3091 static GENERATE_GET_CLASS_WITH_CACHE (generic_ireadonlylist, System.Collections.Generic, IReadOnlyList`1)
3092 static GENERATE_GET_CLASS_WITH_CACHE (generic_ireadonlycollection, System.Collections.Generic, IReadOnlyCollection`1)
3094 /* this won't be needed once bug #325495 is completely fixed
3095 * though we'll need something similar to know which interfaces to allow
3096 * in arrays when they'll be lazyly created
3098 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
3099 * MS returns diferrent types based on which instance is called. For example:
3100 * object obj = new byte[10][];
3101 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
3102 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
3105 * Fixing this should kill quite some code, save some bits and improve compatibility.
3108 get_implicit_generic_array_interfaces (MonoClass *klass, int *num, int *is_enumerator)
3110 MonoClass *eclass = klass->element_class;
3111 MonoClass* generic_icollection_class;
3112 MonoClass* generic_ienumerable_class;
3113 MonoClass* generic_ienumerator_class;
3114 MonoClass* generic_ireadonlylist_class;
3115 MonoClass* generic_ireadonlycollection_class;
3116 MonoClass *valuetype_types[2] = { NULL, NULL };
3117 MonoClass **interfaces = NULL;
3118 int i, nifaces, interface_count, real_count, original_rank;
3120 gboolean internal_enumerator;
3121 gboolean eclass_is_valuetype;
3123 if (!mono_defaults.generic_ilist_class) {
3127 internal_enumerator = FALSE;
3128 eclass_is_valuetype = FALSE;
3129 original_rank = eclass->rank;
3130 if (klass->byval_arg.type != MONO_TYPE_SZARRAY) {
3131 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
3132 if (gklass && klass->nested_in == mono_defaults.array_class && strcmp (klass->name, "InternalEnumerator`1") == 0) {
3134 * For a Enumerator<T[]> we need to get the list of interfaces for T.
3136 eclass = mono_class_from_mono_type (gklass->context.class_inst->type_argv [0]);
3137 original_rank = eclass->rank;
3139 eclass = eclass->element_class;
3140 internal_enumerator = TRUE;
3141 *is_enumerator = TRUE;
3149 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
3150 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
3152 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
3154 generic_icollection_class = mono_class_get_generic_icollection_class ();
3155 generic_ienumerable_class = mono_class_get_generic_ienumerable_class ();
3156 generic_ienumerator_class = mono_class_get_generic_ienumerator_class ();
3157 generic_ireadonlylist_class = mono_class_get_generic_ireadonlylist_class ();
3158 generic_ireadonlycollection_class = mono_class_get_generic_ireadonlycollection_class ();
3160 mono_class_init (eclass);
3163 * Arrays in 2.0 need to implement a number of generic interfaces
3164 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
3165 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
3166 * We collect the types needed to build the
3167 * instantiations in interfaces at intervals of 3/5, because 3/5 are
3168 * the generic interfaces needed to implement.
3170 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
3171 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
3173 if (eclass->valuetype) {
3174 nifaces = generic_ireadonlylist_class ? 5 : 3;
3175 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
3177 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
3178 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
3179 if (internal_enumerator) {
3181 if (valuetype_types [1])
3185 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3186 interfaces [0] = valuetype_types [0];
3187 if (valuetype_types [1])
3188 interfaces [nifaces] = valuetype_types [1];
3190 eclass_is_valuetype = TRUE;
3193 int idepth = eclass->idepth;
3194 if (!internal_enumerator)
3196 nifaces = generic_ireadonlylist_class ? 2 : 3;
3198 // FIXME: This doesn't seem to work/required for generic params
3199 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
3200 mono_class_setup_interface_offsets (eclass);
3202 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
3203 /* we add object for interfaces and the supertypes for the other
3204 * types. The last of the supertypes is the element class itself which we
3205 * already created the explicit interfaces for (so we include it for IEnumerator
3206 * and exclude it for arrays).
3208 if (MONO_CLASS_IS_INTERFACE (eclass))
3211 interface_count += idepth;
3212 if (eclass->rank && eclass->element_class->valuetype) {
3213 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3214 if (valuetype_types [1])
3217 /* IList, ICollection, IEnumerable, IReadOnlyList */
3218 interface_count *= nifaces;
3219 real_count = interface_count;
3220 if (internal_enumerator) {
3221 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3222 if (valuetype_types [1])
3225 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3226 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3227 interfaces [0] = mono_defaults.object_class;
3231 for (i = 0; i < idepth; i++) {
3232 mono_class_init (eclass->supertypes [i]);
3233 interfaces [j] = eclass->supertypes [i];
3237 if (all_interfaces) {
3238 for (i = 0; i < eclass->interface_offsets_count; i++) {
3239 interfaces [j] = eclass->interfaces_packed [i];
3243 for (i = 0; i < eclass->interface_count; i++) {
3244 interfaces [j] = eclass->interfaces [i];
3248 if (valuetype_types [1]) {
3249 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3254 /* instantiate the generic interfaces */
3255 for (i = 0; i < interface_count; i += nifaces) {
3256 MonoClass *iface = interfaces [i];
3258 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3259 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3261 if (eclass->valuetype) {
3262 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3263 if (generic_ireadonlylist_class) {
3264 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3265 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3268 if (!generic_ireadonlylist_class)
3269 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3272 if (internal_enumerator) {
3274 /* instantiate IEnumerator<iface> */
3275 for (i = 0; i < interface_count; i++) {
3276 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3278 j = interface_count;
3279 if (!eclass_is_valuetype) {
3280 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3281 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3284 for (i = 0; i < eclass->idepth; i++) {
3285 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3289 for (i = 0; i < eclass->interface_offsets_count; i++) {
3290 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3294 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3296 if (valuetype_types [1])
3297 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3301 char *type_name = mono_type_get_name_full (&klass->byval_arg, 0);
3302 for (i = 0; i < real_count; ++i) {
3303 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3304 g_print ("%s implements %s\n", type_name, name);
3315 find_array_interface (MonoClass *klass, const char *name)
3318 for (i = 0; i < klass->interface_count; ++i) {
3319 if (strcmp (klass->interfaces [i]->name, name) == 0)
3326 * Return the number of virtual methods.
3327 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3328 * Return -1 on failure.
3329 * FIXME It would be nice if this information could be cached somewhere.
3332 count_virtual_methods (MonoClass *klass)
3336 klass = mono_class_get_generic_type_definition (klass); /*We can find this information by looking at the GTD*/
3338 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
3339 mono_class_setup_methods (klass);
3340 if (mono_class_has_failure (klass))
3343 for (i = 0; i < klass->method.count; ++i) {
3344 flags = klass->methods [i]->flags;
3345 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3349 int first_idx = mono_class_get_first_method_idx (klass);
3350 for (i = 0; i < klass->method.count; ++i) {
3351 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
3353 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3361 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3369 m = (l + num_ifaces) / 2;
3370 if (interfaces_full [m] == ic)
3372 if (l == num_ifaces)
3374 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3383 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3385 int i = find_interface (num_ifaces, interfaces_full, ic);
3387 return interface_offsets_full [i];
3392 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3394 int i = find_interface (num_ifaces, interfaces_full, ic);
3398 interface_offsets_full [i] = offset;
3401 for (i = 0; i < num_ifaces; ++i) {
3402 if (interfaces_full [i]) {
3404 if (interfaces_full [i]->interface_id < ic->interface_id)
3407 while (end < num_ifaces && interfaces_full [end]) end++;
3408 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3409 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3411 interfaces_full [i] = ic;
3412 interface_offsets_full [i] = offset;
3418 #ifdef COMPRESSED_INTERFACE_BITMAP
3421 * Compressed interface bitmap design.
3423 * Interface bitmaps take a large amount of memory, because their size is
3424 * linear with the maximum interface id assigned in the process (each interface
3425 * is assigned a unique id as it is loaded). The number of interface classes
3426 * is high because of the many implicit interfaces implemented by arrays (we'll
3427 * need to lazy-load them in the future).
3428 * Most classes implement a very small number of interfaces, so the bitmap is
3429 * sparse. This bitmap needs to be checked by interface casts, so access to the
3430 * needed bit must be fast and doable with few jit instructions.
3432 * The current compression format is as follows:
3433 * *) it is a sequence of one or more two-byte elements
3434 * *) the first byte in the element is the count of empty bitmap bytes
3435 * at the current bitmap position
3436 * *) the second byte in the element is an actual bitmap byte at the current
3439 * As an example, the following compressed bitmap bytes:
3440 * 0x07 0x01 0x00 0x7
3441 * correspond to the following bitmap:
3442 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3444 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3445 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3446 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3450 * mono_compress_bitmap:
3451 * @dest: destination buffer
3452 * @bitmap: bitmap buffer
3453 * @size: size of @bitmap in bytes
3455 * This is a mono internal function.
3456 * The @bitmap data is compressed into a format that is small but
3457 * still searchable in few instructions by the JIT and runtime.
3458 * The compressed data is stored in the buffer pointed to by the
3459 * @dest array. Passing a #NULL value for @dest allows to just compute
3460 * the size of the buffer.
3461 * This compression algorithm assumes the bits set in the bitmap are
3462 * few and far between, like in interface bitmaps.
3463 * Returns: The size of the compressed bitmap in bytes.
3466 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3470 const uint8_t *end = bitmap + size;
3471 while (bitmap < end) {
3472 if (*bitmap || numz == 255) {
3496 * mono_class_interface_match:
3497 * @bitmap: a compressed bitmap buffer
3498 * @id: the index to check in the bitmap
3500 * This is a mono internal function.
3501 * Checks if a bit is set in a compressed interface bitmap. @id must
3502 * be already checked for being smaller than the maximum id encoded in the
3505 * Returns: A non-zero value if bit @id is set in the bitmap @bitmap,
3509 mono_class_interface_match (const uint8_t *bitmap, int id)
3512 id -= bitmap [0] * 8;
3516 return bitmap [1] & (1 << id);
3525 * Return -1 on failure and set klass->has_failure and store a MonoErrorBoxed with the details.
3526 * LOCKING: Acquires the loader lock.
3529 setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite)
3533 int i, j, num_ifaces;
3535 MonoClass **interfaces_full = NULL;
3536 int *interface_offsets_full = NULL;
3538 GPtrArray **ifaces_array = NULL;
3539 int interface_offsets_count;
3540 MonoClass **array_interfaces = NULL;
3541 int num_array_interfaces;
3542 int is_enumerator = FALSE;
3544 mono_class_setup_supertypes (klass);
3546 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3547 * implicit interfaces have the property that they are assigned the same slot in the
3548 * vtables for compatible interfaces
3550 array_interfaces = get_implicit_generic_array_interfaces (klass, &num_array_interfaces, &is_enumerator);
3552 /* compute maximum number of slots and maximum interface id */
3554 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3555 ifaces_array = g_new0 (GPtrArray *, klass->idepth);
3556 for (j = 0; j < klass->idepth; j++) {
3557 k = klass->supertypes [j];
3558 num_ifaces += k->interface_count;
3559 for (i = 0; i < k->interface_count; i++) {
3560 ic = k->interfaces [i];
3562 mono_class_init (ic);
3564 if (max_iid < ic->interface_id)
3565 max_iid = ic->interface_id;
3567 ifaces = mono_class_get_implemented_interfaces (k, &error);
3568 if (!mono_error_ok (&error)) {
3569 char *name = mono_type_get_full_name (k);
3570 mono_class_set_type_load_failure (klass, "Error getting the interfaces of %s due to %s", name, mono_error_get_message (&error));
3572 mono_error_cleanup (&error);
3577 num_ifaces += ifaces->len;
3578 for (i = 0; i < ifaces->len; ++i) {
3579 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3580 if (max_iid < ic->interface_id)
3581 max_iid = ic->interface_id;
3583 ifaces_array [j] = ifaces;
3587 for (i = 0; i < num_array_interfaces; ++i) {
3588 ic = array_interfaces [i];
3589 mono_class_init (ic);
3590 if (max_iid < ic->interface_id)
3591 max_iid = ic->interface_id;
3594 if (MONO_CLASS_IS_INTERFACE (klass)) {
3596 if (max_iid < klass->interface_id)
3597 max_iid = klass->interface_id;
3600 /* compute vtable offset for interfaces */
3601 interfaces_full = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3602 interface_offsets_full = (int *)g_malloc (sizeof (int) * num_ifaces);
3604 for (i = 0; i < num_ifaces; i++)
3605 interface_offsets_full [i] = -1;
3607 /* skip the current class */
3608 for (j = 0; j < klass->idepth - 1; j++) {
3609 k = klass->supertypes [j];
3610 ifaces = ifaces_array [j];
3613 for (i = 0; i < ifaces->len; ++i) {
3615 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3617 /*Force the sharing of interface offsets between parent and subtypes.*/
3618 io = mono_class_interface_offset (k, ic);
3620 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3625 g_assert (klass == klass->supertypes [klass->idepth - 1]);
3626 ifaces = ifaces_array [klass->idepth - 1];
3628 for (i = 0; i < ifaces->len; ++i) {
3630 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3631 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3633 count = count_virtual_methods (ic);
3635 char *name = mono_type_get_full_name (ic);
3636 mono_class_set_type_load_failure (klass, "Error calculating interface offset of %s", name);
3645 if (MONO_CLASS_IS_INTERFACE (klass))
3646 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, klass, cur_slot, TRUE);
3648 if (num_array_interfaces) {
3649 if (is_enumerator) {
3650 int ienumerator_idx = find_array_interface (klass, "IEnumerator`1");
3651 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ienumerator_idx]);
3652 g_assert (ienumerator_offset >= 0);
3653 for (i = 0; i < num_array_interfaces; ++i) {
3654 ic = array_interfaces [i];
3655 if (strcmp (ic->name, "IEnumerator`1") == 0)
3656 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3658 g_assert_not_reached ();
3659 /*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);*/
3662 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3663 int ilist_iface_idx = find_array_interface (klass, "IList`1");
3664 MonoClass* ilist_class = klass->interfaces [ilist_iface_idx];
3665 int ireadonlylist_iface_idx = find_array_interface (klass, "IReadOnlyList`1");
3666 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? klass->interfaces [ireadonlylist_iface_idx] : NULL;
3667 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3668 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3669 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3670 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ilist_iface_idx]);
3671 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3672 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3673 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ireadonlylist_iface_idx]) : -1;
3674 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3675 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3676 for (i = 0; i < num_array_interfaces; ++i) {
3678 ic = array_interfaces [i];
3679 if (mono_class_get_generic_class (ic)->container_class == mono_defaults.generic_ilist_class)
3680 offset = ilist_offset;
3681 else if (strcmp (ic->name, "ICollection`1") == 0)
3682 offset = icollection_offset;
3683 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3684 offset = ienumerable_offset;
3685 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3686 offset = ireadonlylist_offset;
3687 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3688 offset = ireadonlycollection_offset;
3690 g_assert_not_reached ();
3691 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3692 /*g_print ("type %s has %s offset at %d (%s)\n", klass->name, ic->name, offset, klass->interfaces [0]->name);*/
3697 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3698 if (interface_offsets_full [i] != -1)
3699 interface_offsets_count ++;
3702 /* Publish the data */
3703 mono_loader_lock ();
3705 klass->max_interface_id = max_iid;
3707 * We might get called multiple times:
3708 * - mono_class_init ()
3709 * - mono_class_setup_vtable ().
3710 * - mono_class_setup_interface_offsets ().
3711 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3712 * means we have to overwrite those when called from other places (#4440).
3714 if (klass->interfaces_packed) {
3716 g_assert (klass->interface_offsets_count == interface_offsets_count);
3720 klass->interface_offsets_count = interface_offsets_count;
3721 klass->interfaces_packed = (MonoClass **)mono_class_alloc (klass, sizeof (MonoClass*) * interface_offsets_count);
3722 klass->interface_offsets_packed = (guint16 *)mono_class_alloc (klass, sizeof (guint16) * interface_offsets_count);
3723 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3724 #ifdef COMPRESSED_INTERFACE_BITMAP
3725 bitmap = g_malloc0 (bsize);
3727 bitmap = (uint8_t *)mono_class_alloc0 (klass, bsize);
3729 for (i = 0; i < interface_offsets_count; i++) {
3730 guint32 id = interfaces_full [i]->interface_id;
3731 bitmap [id >> 3] |= (1 << (id & 7));
3732 klass->interfaces_packed [i] = interfaces_full [i];
3733 klass->interface_offsets_packed [i] = interface_offsets_full [i];
3734 /*if (num_array_interfaces)
3735 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]);*/
3737 #ifdef COMPRESSED_INTERFACE_BITMAP
3738 i = mono_compress_bitmap (NULL, bitmap, bsize);
3739 klass->interface_bitmap = mono_class_alloc0 (klass, i);
3740 mono_compress_bitmap (klass->interface_bitmap, bitmap, bsize);
3743 klass->interface_bitmap = bitmap;
3746 mono_loader_unlock ();
3749 g_free (interfaces_full);
3750 g_free (interface_offsets_full);
3751 g_free (array_interfaces);
3752 for (i = 0; i < klass->idepth; i++) {
3753 ifaces = ifaces_array [i];
3755 g_ptr_array_free (ifaces, TRUE);
3757 g_free (ifaces_array);
3759 //printf ("JUST DONE: ");
3760 //print_implemented_interfaces (klass);
3766 * Setup interface offsets for interfaces.
3768 * - klass->max_interface_id
3769 * - klass->interface_offsets_count
3770 * - klass->interfaces_packed
3771 * - klass->interface_offsets_packed
3772 * - klass->interface_bitmap
3774 * This function can fail @class.
3777 mono_class_setup_interface_offsets (MonoClass *klass)
3779 setup_interface_offsets (klass, 0, FALSE);
3782 /*Checks if @klass has @parent as one of it's parents type gtd
3786 * Bar<T> : Foo<Bar<Bar<T>>>
3790 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3792 klass = mono_class_get_generic_type_definition (klass);
3793 parent = mono_class_get_generic_type_definition (parent);
3794 mono_class_setup_supertypes (klass);
3795 mono_class_setup_supertypes (parent);
3797 return klass->idepth >= parent->idepth &&
3798 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3802 mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup)
3804 MonoGenericInst *ginst;
3807 if (!mono_class_is_ginst (klass)) {
3808 mono_class_setup_vtable_full (klass, in_setup);
3809 return !mono_class_has_failure (klass);
3812 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup);
3813 if (mono_class_set_type_load_failure_causedby_class (klass, mono_class_get_generic_class (klass)->container_class, "Failed to load generic definition vtable"))
3816 ginst = mono_class_get_generic_class (klass)->context.class_inst;
3817 for (i = 0; i < ginst->type_argc; ++i) {
3819 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3821 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3822 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3823 if (mono_class_has_gtd_parent (klass, arg) || mono_class_has_gtd_parent (arg, klass))
3825 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3826 mono_class_set_type_load_failure (klass, "Failed to load generic parameter %d", i);
3834 * mono_class_setup_vtable:
3836 * Creates the generic vtable of CLASS.
3837 * Initializes the following fields in MonoClass:
3840 * Plus all the fields initialized by setup_interface_offsets ().
3841 * If there is an error during vtable construction, klass->has_failure
3842 * is set and details are stored in a MonoErrorBoxed.
3844 * LOCKING: Acquires the loader lock.
3847 mono_class_setup_vtable (MonoClass *klass)
3849 mono_class_setup_vtable_full (klass, NULL);
3853 mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
3856 MonoMethod **overrides;
3857 MonoGenericContext *context;
3865 if (MONO_CLASS_IS_INTERFACE (klass)) {
3866 /* This sets method->slot for all methods if this is an interface */
3867 mono_class_setup_methods (klass);
3871 if (mono_class_has_failure (klass))
3874 if (g_list_find (in_setup, klass))
3877 mono_loader_lock ();
3879 if (klass->vtable) {
3880 mono_loader_unlock ();
3884 mono_stats.generic_vtable_count ++;
3885 in_setup = g_list_prepend (in_setup, klass);
3887 if (mono_class_is_ginst (klass)) {
3888 if (!mono_class_check_vtable_constraints (klass, in_setup)) {
3889 mono_loader_unlock ();
3890 g_list_remove (in_setup, klass);
3894 context = mono_class_get_context (klass);
3895 type_token = mono_class_get_generic_class (klass)->container_class->type_token;
3897 context = (MonoGenericContext *) mono_class_try_get_generic_container (klass); //FIXME is this a case of a try?
3898 type_token = klass->type_token;
3901 if (image_is_dynamic (klass->image)) {
3902 /* Generic instances can have zero method overrides without causing any harm.
3903 * This is true since we don't do layout all over again for them, we simply inflate
3904 * the layout of the parent.
3906 mono_reflection_get_dynamic_overrides (klass, &overrides, &onum, &error);
3907 if (!is_ok (&error)) {
3908 mono_loader_unlock ();
3909 g_list_remove (in_setup, klass);
3910 mono_class_set_type_load_failure (klass, "Could not load list of method overrides due to %s", mono_error_get_message (&error));
3911 mono_error_cleanup (&error);
3915 /* The following call fails if there are missing methods in the type */
3916 /* FIXME it's probably a good idea to avoid this for generic instances. */
3917 ok = mono_class_get_overrides_full (klass->image, type_token, &overrides, &onum, context);
3921 mono_class_setup_vtable_general (klass, overrides, onum, in_setup);
3923 mono_class_set_type_load_failure (klass, "Could not load list of method overrides");
3927 mono_loader_unlock ();
3928 g_list_remove (in_setup, klass);
3933 #define DEBUG_INTERFACE_VTABLE_CODE 0
3934 #define TRACE_INTERFACE_VTABLE_CODE 0
3935 #define VERIFY_INTERFACE_VTABLE_CODE 0
3936 #define VTABLE_SELECTOR (1)
3938 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3939 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3940 if (!(VTABLE_SELECTOR)) break; \
3944 #define DEBUG_INTERFACE_VTABLE(stmt)
3947 #if TRACE_INTERFACE_VTABLE_CODE
3948 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3949 if (!(VTABLE_SELECTOR)) break; \
3953 #define TRACE_INTERFACE_VTABLE(stmt)
3956 #if VERIFY_INTERFACE_VTABLE_CODE
3957 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3958 if (!(VTABLE_SELECTOR)) break; \
3962 #define VERIFY_INTERFACE_VTABLE(stmt)
3966 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3968 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3972 GString *res = g_string_new ("");
3974 g_string_append_c (res, '(');
3975 for (i = 0; i < sig->param_count; ++i) {
3977 g_string_append_c (res, ',');
3978 mono_type_get_desc (res, sig->params [i], include_namespace);
3980 g_string_append (res, ")=>");
3981 if (sig->ret != NULL) {
3982 mono_type_get_desc (res, sig->ret, include_namespace);
3984 g_string_append (res, "NULL");
3987 g_string_free (res, FALSE);
3991 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3992 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3993 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3994 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
4002 is_wcf_hack_disabled (void)
4004 static gboolean disabled;
4005 static gboolean inited = FALSE;
4007 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
4014 check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
4016 MonoMethodSignature *cmsig, *imsig;
4017 if (strcmp (im->name, cm->name) == 0) {
4018 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
4019 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
4022 if (! slot_is_empty) {
4023 if (require_newslot) {
4024 if (! interface_is_explicitly_implemented_by_class) {
4025 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
4028 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4029 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
4033 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
4036 cmsig = mono_method_signature (cm);
4037 imsig = mono_method_signature (im);
4038 if (!cmsig || !imsig) {
4039 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
4043 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4044 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
4045 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4046 TRACE_INTERFACE_VTABLE (printf ("]"));
4049 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
4050 if (mono_security_core_clr_enabled ())
4051 mono_security_core_clr_check_override (klass, cm, im);
4053 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
4054 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4055 char *body_name = mono_method_full_name (cm, TRUE);
4056 char *decl_name = mono_method_full_name (im, TRUE);
4057 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4065 MonoClass *ic = im->klass;
4066 const char *ic_name_space = ic->name_space;
4067 const char *ic_name = ic->name;
4070 if (! require_newslot) {
4071 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
4074 if (cm->klass->rank == 0) {
4075 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
4078 cmsig = mono_method_signature (cm);
4079 imsig = mono_method_signature (im);
4080 if (!cmsig || !imsig) {
4081 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
4085 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4086 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
4087 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4088 TRACE_INTERFACE_VTABLE (printf ("]"));
4091 if (mono_class_get_image (ic) != mono_defaults.corlib) {
4092 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
4095 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
4096 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
4099 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))) {
4100 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
4104 subname = strstr (cm->name, ic_name_space);
4105 if (subname != cm->name) {
4106 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
4109 subname += strlen (ic_name_space);
4110 if (subname [0] != '.') {
4111 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
4115 if (strstr (subname, ic_name) != subname) {
4116 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
4119 subname += strlen (ic_name);
4120 if (subname [0] != '.') {
4121 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
4125 if (strcmp (subname, im->name) != 0) {
4126 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
4130 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
4131 if (mono_security_core_clr_enabled ())
4132 mono_security_core_clr_check_override (klass, cm, im);
4134 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
4135 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4136 char *body_name = mono_method_full_name (cm, TRUE);
4137 char *decl_name = mono_method_full_name (im, TRUE);
4138 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4148 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
4150 foreach_override (gpointer key, gpointer value, gpointer user_data) {
4151 MonoMethod *method = key;
4152 MonoMethod *override = value;
4153 MonoClass *method_class = mono_method_get_class (method);
4154 MonoClass *override_class = mono_method_get_class (override);
4156 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
4157 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
4158 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
4161 print_overrides (GHashTable *override_map, const char *message) {
4163 printf ("Override map \"%s\" START:\n", message);
4164 g_hash_table_foreach (override_map, foreach_override, NULL);
4165 printf ("Override map \"%s\" END.\n", message);
4167 printf ("Override map \"%s\" EMPTY.\n", message);
4171 print_vtable_full (MonoClass *klass, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
4172 char *full_name = mono_type_full_name (&klass->byval_arg);
4176 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
4178 if (print_interfaces) {
4179 print_implemented_interfaces (klass);
4180 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
4183 if (klass->parent) {
4184 parent_size = klass->parent->vtable_size;
4188 for (i = 0; i < size; ++i) {
4189 MonoMethod *cm = vtable [i];
4190 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
4191 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
4193 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
4201 #if VERIFY_INTERFACE_VTABLE_CODE
4203 mono_method_try_get_vtable_index (MonoMethod *method)
4205 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4206 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4207 if (imethod->declaring->is_generic)
4208 return imethod->declaring->slot;
4210 return method->slot;
4214 mono_class_verify_vtable (MonoClass *klass)
4217 char *full_name = mono_type_full_name (&klass->byval_arg);
4219 printf ("*** Verifying VTable of class '%s' \n", full_name);
4223 if (!klass->methods)
4226 for (i = 0; i < klass->method.count; ++i) {
4227 MonoMethod *cm = klass->methods [i];
4230 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4234 full_name = mono_method_full_name (cm, TRUE);
4236 slot = mono_method_try_get_vtable_index (cm);
4238 if (slot >= klass->vtable_size) {
4239 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, klass->vtable_size);
4243 if (slot >= 0 && klass->vtable [slot] != cm && (klass->vtable [slot])) {
4244 char *other_name = klass->vtable [slot] ? mono_method_full_name (klass->vtable [slot], TRUE) : g_strdup ("[null value]");
4245 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4246 g_free (other_name);
4249 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4256 print_unimplemented_interface_method_info (MonoClass *klass, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4258 char *method_signature;
4261 for (index = 0; index < onum; ++index) {
4262 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4263 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4265 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4266 type_name = mono_type_full_name (&klass->byval_arg);
4267 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4268 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4269 g_free (method_signature);
4271 mono_class_setup_methods (klass);
4272 if (mono_class_has_failure (klass)) {
4273 char *name = mono_type_get_full_name (klass);
4274 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4278 for (index = 0; index < klass->method.count; ++index) {
4279 MonoMethod *cm = klass->methods [index];
4280 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4282 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4283 g_free (method_signature);
4288 mono_method_get_method_definition (MonoMethod *method)
4290 while (method->is_inflated)
4291 method = ((MonoMethodInflated*)method)->declaring;
4296 verify_class_overrides (MonoClass *klass, MonoMethod **overrides, int onum)
4300 for (i = 0; i < onum; ++i) {
4301 MonoMethod *decl = overrides [i * 2];
4302 MonoMethod *body = overrides [i * 2 + 1];
4304 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (klass)) {
4305 mono_class_set_type_load_failure (klass, "Method belongs to a different class than the declared one");
4309 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4310 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4311 mono_class_set_type_load_failure (klass, "Method must not be static to override a base type");
4313 mono_class_set_type_load_failure (klass, "Method must be virtual to override a base type");
4317 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4318 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4319 mono_class_set_type_load_failure (klass, "Cannot override a static method in a base type");
4321 mono_class_set_type_load_failure (klass, "Cannot override a non virtual method in a base type");
4325 if (!mono_class_is_assignable_from_slow (decl->klass, klass)) {
4326 mono_class_set_type_load_failure (klass, "Method overrides a class or interface that is not extended or implemented by this type");
4330 body = mono_method_get_method_definition (body);
4331 decl = mono_method_get_method_definition (decl);
4333 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4334 char *body_name = mono_method_full_name (body, TRUE);
4335 char *decl_name = mono_method_full_name (decl, TRUE);
4336 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4346 mono_class_need_stelemref_method (MonoClass *klass)
4348 return klass->rank == 1 && MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg);
4352 * LOCKING: this is supposed to be called with the loader lock held.
4355 mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int onum, GList *in_setup)
4359 MonoMethod **vtable;
4360 int i, max_vtsize = 0, cur_slot = 0;
4362 GPtrArray *ifaces = NULL;
4363 GHashTable *override_map = NULL;
4365 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4366 int first_non_interface_slot;
4368 GSList *virt_methods = NULL, *l;
4369 int stelemref_slot = 0;
4374 if (overrides && !verify_class_overrides (klass, overrides, onum))
4377 ifaces = mono_class_get_implemented_interfaces (klass, &error);
4378 if (!mono_error_ok (&error)) {
4379 char *name = mono_type_get_full_name (klass);
4380 mono_class_set_type_load_failure (klass, "Could not resolve %s interfaces due to %s", name, mono_error_get_message (&error));
4382 mono_error_cleanup (&error);
4384 } else if (ifaces) {
4385 for (i = 0; i < ifaces->len; i++) {
4386 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
4387 max_vtsize += ic->method.count;
4389 g_ptr_array_free (ifaces, TRUE);
4393 if (klass->parent) {
4394 mono_class_init (klass->parent);
4395 mono_class_setup_vtable_full (klass->parent, in_setup);
4397 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class failed to load"))
4400 max_vtsize += klass->parent->vtable_size;
4401 cur_slot = klass->parent->vtable_size;
4404 max_vtsize += klass->method.count;
4406 /*Array have a slot for stelemref*/
4407 if (mono_class_need_stelemref_method (klass)) {
4408 stelemref_slot = cur_slot;
4413 vtable = (MonoMethod **)alloca (sizeof (gpointer) * max_vtsize);
4414 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4416 /* printf ("METAINIT %s.%s\n", klass->name_space, klass->name); */
4418 cur_slot = setup_interface_offsets (klass, cur_slot, TRUE);
4419 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4422 max_iid = klass->max_interface_id;
4423 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4425 /* Optimized version for generic instances */
4426 if (mono_class_is_ginst (klass)) {
4428 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4431 mono_class_setup_vtable_full (gklass, in_setup);
4432 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Could not load generic definition"))
4435 tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * gklass->vtable_size);
4436 klass->vtable_size = gklass->vtable_size;
4437 for (i = 0; i < gklass->vtable_size; ++i)
4438 if (gklass->vtable [i]) {
4439 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], klass, mono_class_get_context (klass), &error);
4440 if (!mono_error_ok (&error)) {
4441 mono_class_set_type_load_failure (klass, "Could not inflate method due to %s", mono_error_get_message (&error));
4442 mono_error_cleanup (&error);
4446 tmp [i]->slot = gklass->vtable [i]->slot;
4448 mono_memory_barrier ();
4449 klass->vtable = tmp;
4451 /* Have to set method->slot for abstract virtual methods */
4452 if (klass->methods && gklass->methods) {
4453 for (i = 0; i < klass->method.count; ++i)
4454 if (klass->methods [i]->slot == -1)
4455 klass->methods [i]->slot = gklass->methods [i]->slot;
4461 if (klass->parent && klass->parent->vtable_size) {
4462 MonoClass *parent = klass->parent;
4465 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4467 // Also inherit parent interface vtables, just as a starting point.
4468 // This is needed otherwise bug-77127.exe fails when the property methods
4469 // have different names in the iterface and the class, because for child
4470 // classes the ".override" information is not used anymore.
4471 for (i = 0; i < parent->interface_offsets_count; i++) {
4472 MonoClass *parent_interface = parent->interfaces_packed [i];
4473 int interface_offset = mono_class_interface_offset (klass, parent_interface);
4474 /*FIXME this is now dead code as this condition will never hold true.
4475 Since interface offsets are inherited then the offset of an interface implemented
4476 by a parent will never be the out of it's vtable boundary.
4478 if (interface_offset >= parent->vtable_size) {
4479 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4482 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4483 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4484 for (j = 0; j < parent_interface->method.count && !mono_class_has_failure (klass); j++) {
4485 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4486 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4487 parent_interface_offset + j, parent_interface_offset, j,
4488 interface_offset + j, interface_offset, j));
4495 /*Array have a slot for stelemref*/
4496 if (mono_class_need_stelemref_method (klass)) {
4497 MonoMethod *method = mono_marshal_get_virtual_stelemref (klass);
4499 method->slot = stelemref_slot;
4501 g_assert (method->slot == stelemref_slot);
4503 vtable [stelemref_slot] = method;
4506 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4507 /* override interface methods */
4508 for (i = 0; i < onum; i++) {
4509 MonoMethod *decl = overrides [i*2];
4510 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4512 dslot = mono_method_get_vtable_slot (decl);
4514 mono_class_set_type_load_failure (klass, "");
4518 dslot += mono_class_interface_offset (klass, decl->klass);
4519 vtable [dslot] = overrides [i*2 + 1];
4520 vtable [dslot]->slot = dslot;
4522 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4524 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4526 if (mono_security_core_clr_enabled ())
4527 mono_security_core_clr_check_override (klass, vtable [dslot], decl);
4530 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4531 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4534 * Create a list of virtual methods to avoid calling
4535 * mono_class_get_virtual_methods () which is slow because of the metadata
4539 gpointer iter = NULL;
4542 virt_methods = NULL;
4543 while ((cm = mono_class_get_virtual_methods (klass, &iter))) {
4544 virt_methods = g_slist_prepend (virt_methods, cm);
4546 if (mono_class_has_failure (klass))
4550 // Loop on all implemented interfaces...
4551 for (i = 0; i < klass->interface_offsets_count; i++) {
4552 MonoClass *parent = klass->parent;
4554 gboolean interface_is_explicitly_implemented_by_class;
4557 ic = klass->interfaces_packed [i];
4558 ic_offset = mono_class_interface_offset (klass, ic);
4560 mono_class_setup_methods (ic);
4561 if (mono_class_has_failure (ic))
4564 // Check if this interface is explicitly implemented (instead of just inherited)
4565 if (parent != NULL) {
4566 int implemented_interfaces_index;
4567 interface_is_explicitly_implemented_by_class = FALSE;
4568 for (implemented_interfaces_index = 0; implemented_interfaces_index < klass->interface_count; implemented_interfaces_index++) {
4569 if (ic == klass->interfaces [implemented_interfaces_index]) {
4570 interface_is_explicitly_implemented_by_class = TRUE;
4575 interface_is_explicitly_implemented_by_class = TRUE;
4578 // Loop on all interface methods...
4579 for (im_index = 0; im_index < ic->method.count; im_index++) {
4580 MonoMethod *im = ic->methods [im_index];
4581 int im_slot = ic_offset + im->slot;
4582 MonoMethod *override_im = (override_map != NULL) ? (MonoMethod *)g_hash_table_lookup (override_map, im) : NULL;
4584 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4587 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4589 // If there is an explicit implementation, just use it right away,
4590 // otherwise look for a matching method
4591 if (override_im == NULL) {
4595 // First look for a suitable method among the class methods
4596 for (l = virt_methods; l; l = l->next) {
4597 cm = (MonoMethod *)l->data;
4598 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)));
4599 if (check_interface_method_override (klass, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
4600 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4601 vtable [im_slot] = cm;
4602 /* Why do we need this? */
4607 TRACE_INTERFACE_VTABLE (printf ("\n"));
4608 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4612 // If the slot is still empty, look in all the inherited virtual methods...
4613 if ((vtable [im_slot] == NULL) && klass->parent != NULL) {
4614 MonoClass *parent = klass->parent;
4615 // Reverse order, so that last added methods are preferred
4616 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4617 MonoMethod *cm = parent->vtable [cm_index];
4619 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));
4620 if ((cm != NULL) && check_interface_method_override (klass, im, cm, FALSE, FALSE, TRUE)) {
4621 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4622 vtable [im_slot] = cm;
4623 /* Why do we need this? */
4629 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4631 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4635 g_assert (vtable [im_slot] == override_im);
4640 // If the class is not abstract, check that all its interface slots are full.
4641 // The check is done here and not directly at the end of the loop above because
4642 // it can happen (for injected generic array interfaces) that the same slot is
4643 // processed multiple times (those interfaces have overlapping slots), and it
4644 // will not always be the first pass the one that fills the slot.
4645 if (!mono_class_is_abstract (klass)) {
4646 for (i = 0; i < klass->interface_offsets_count; i++) {
4650 ic = klass->interfaces_packed [i];
4651 ic_offset = mono_class_interface_offset (klass, ic);
4653 for (im_index = 0; im_index < ic->method.count; im_index++) {
4654 MonoMethod *im = ic->methods [im_index];
4655 int im_slot = ic_offset + im->slot;
4657 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4660 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4661 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4662 if (vtable [im_slot] == NULL) {
4663 print_unimplemented_interface_method_info (klass, ic, im, im_slot, overrides, onum);
4670 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4671 for (l = virt_methods; l; l = l->next) {
4672 cm = (MonoMethod *)l->data;
4674 * If the method is REUSE_SLOT, we must check in the
4675 * base class for a method to override.
4677 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4679 for (k = klass->parent; k ; k = k->parent) {
4684 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4685 MonoMethodSignature *cmsig, *m1sig;
4687 cmsig = mono_method_signature (cm);
4688 m1sig = mono_method_signature (m1);
4690 if (!cmsig || !m1sig) {
4691 /* FIXME proper error message */
4692 mono_class_set_type_load_failure (klass, "");
4696 if (!strcmp(cm->name, m1->name) &&
4697 mono_metadata_signature_equal (cmsig, m1sig)) {
4699 if (mono_security_core_clr_enabled ())
4700 mono_security_core_clr_check_override (klass, cm, m1);
4702 slot = mono_method_get_vtable_slot (m1);
4706 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4707 char *body_name = mono_method_full_name (cm, TRUE);
4708 char *decl_name = mono_method_full_name (m1, TRUE);
4709 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4715 g_assert (cm->slot < max_vtsize);
4717 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4718 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4719 mono_method_full_name (m1, 1), m1,
4720 mono_method_full_name (cm, 1), cm));
4721 g_hash_table_insert (override_map, m1, cm);
4725 if (mono_class_has_failure (k))
4735 /*Non final newslot methods must be given a non-interface vtable slot*/
4736 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4740 cm->slot = cur_slot++;
4742 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4743 vtable [cm->slot] = cm;
4746 /* override non interface methods */
4747 for (i = 0; i < onum; i++) {
4748 MonoMethod *decl = overrides [i*2];
4749 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4750 g_assert (decl->slot != -1);
4751 vtable [decl->slot] = overrides [i*2 + 1];
4752 overrides [i * 2 + 1]->slot = decl->slot;
4754 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4755 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4756 mono_method_full_name (decl, 1), decl,
4757 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4758 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4760 if (mono_security_core_clr_enabled ())
4761 mono_security_core_clr_check_override (klass, vtable [decl->slot], decl);
4766 * If a method occupies more than one place in the vtable, and it is
4767 * overriden, then change the other occurances too.
4772 for (i = 0; i < max_vtsize; ++i)
4774 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4776 cm = (MonoMethod *)g_hash_table_lookup (override_map, vtable [i]);
4781 g_hash_table_destroy (override_map);
4782 override_map = NULL;
4785 g_slist_free (virt_methods);
4786 virt_methods = NULL;
4788 /* Ensure that all vtable slots are filled with concrete instance methods */
4789 if (!mono_class_is_abstract (klass)) {
4790 for (i = 0; i < cur_slot; ++i) {
4791 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4792 char *type_name = mono_type_get_full_name (klass);
4793 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4794 mono_class_set_type_load_failure (klass, "Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name);
4796 g_free (method_name);
4802 if (mono_class_is_ginst (klass)) {
4803 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4805 mono_class_init (gklass);
4807 klass->vtable_size = MAX (gklass->vtable_size, cur_slot);
4809 /* Check that the vtable_size value computed in mono_class_init () is correct */
4810 if (klass->vtable_size)
4811 g_assert (cur_slot == klass->vtable_size);
4812 klass->vtable_size = cur_slot;
4815 /* Try to share the vtable with our parent. */
4816 if (klass->parent && (klass->parent->vtable_size == klass->vtable_size) && (memcmp (klass->parent->vtable, vtable, sizeof (gpointer) * klass->vtable_size) == 0)) {
4817 mono_memory_barrier ();
4818 klass->vtable = klass->parent->vtable;
4820 MonoMethod **tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * klass->vtable_size);
4821 memcpy (tmp, vtable, sizeof (gpointer) * klass->vtable_size);
4822 mono_memory_barrier ();
4823 klass->vtable = tmp;
4826 DEBUG_INTERFACE_VTABLE (print_vtable_full (klass, klass->vtable, klass->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4827 if (mono_print_vtable) {
4830 print_implemented_interfaces (klass);
4832 for (i = 0; i <= max_iid; i++)
4833 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
4836 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&klass->byval_arg),
4837 klass->vtable_size, icount);
4839 for (i = 0; i < cur_slot; ++i) {
4844 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4845 mono_method_full_name (cm, TRUE));
4851 printf ("Interfaces %s.%s (max_iid = %d)\n", klass->name_space,
4852 klass->name, max_iid);
4854 for (i = 0; i < klass->interface_count; i++) {
4855 ic = klass->interfaces [i];
4856 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4857 mono_class_interface_offset (klass, ic),
4858 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4861 for (k = klass->parent; k ; k = k->parent) {
4862 for (i = 0; i < k->interface_count; i++) {
4863 ic = k->interfaces [i];
4864 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4865 mono_class_interface_offset (klass, ic),
4866 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4872 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (klass));
4877 char *name = mono_type_get_full_name (klass);
4878 mono_class_set_type_load_failure (klass, "VTable setup of type %s failed", name);
4881 g_hash_table_destroy (override_map);
4883 g_slist_free (virt_methods);
4888 * mono_method_get_vtable_slot:
4890 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4891 * LOCKING: Acquires the loader lock.
4893 * FIXME Use proper MonoError machinery here.
4896 mono_method_get_vtable_slot (MonoMethod *method)
4898 if (method->slot == -1) {
4899 mono_class_setup_vtable (method->klass);
4900 if (mono_class_has_failure (method->klass))
4902 if (method->slot == -1) {
4906 if (!mono_class_is_ginst (method->klass)) {
4907 g_assert (method->is_inflated);
4908 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4911 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4912 g_assert (mono_class_is_ginst (method->klass));
4913 gklass = mono_class_get_generic_class (method->klass)->container_class;
4914 mono_class_setup_methods (method->klass);
4915 g_assert (method->klass->methods);
4916 for (i = 0; i < method->klass->method.count; ++i) {
4917 if (method->klass->methods [i] == method)
4920 g_assert (i < method->klass->method.count);
4921 g_assert (gklass->methods);
4922 method->slot = gklass->methods [i]->slot;
4924 g_assert (method->slot != -1);
4926 return method->slot;
4930 * mono_method_get_vtable_index:
4933 * Returns the index into the runtime vtable to access the method or,
4934 * in the case of a virtual generic method, the virtual generic method
4935 * thunk. Returns -1 on failure.
4937 * FIXME Use proper MonoError machinery here.
4940 mono_method_get_vtable_index (MonoMethod *method)
4942 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4943 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4944 if (imethod->declaring->is_generic)
4945 return mono_method_get_vtable_slot (imethod->declaring);
4947 return mono_method_get_vtable_slot (method);
4950 static MonoMethod *default_ghc = NULL;
4951 static MonoMethod *default_finalize = NULL;
4952 static int finalize_slot = -1;
4953 static int ghc_slot = -1;
4956 initialize_object_slots (MonoClass *klass)
4961 if (klass == mono_defaults.object_class) {
4962 mono_class_setup_vtable (klass);
4963 for (i = 0; i < klass->vtable_size; ++i) {
4964 MonoMethod *cm = klass->vtable [i];
4966 if (!strcmp (cm->name, "GetHashCode"))
4968 else if (!strcmp (cm->name, "Finalize"))
4972 g_assert (ghc_slot > 0);
4973 default_ghc = klass->vtable [ghc_slot];
4975 g_assert (finalize_slot > 0);
4976 default_finalize = klass->vtable [finalize_slot];
4981 MonoMethod *array_method;
4983 } GenericArrayMethodInfo;
4985 static int generic_array_method_num = 0;
4986 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4989 generic_array_methods (MonoClass *klass)
4991 int i, count_generic = 0;
4992 GList *list = NULL, *tmp;
4993 if (generic_array_method_num)
4994 return generic_array_method_num;
4995 mono_class_setup_methods (klass->parent); /*This is setting up System.Array*/
4996 g_assert (!mono_class_has_failure (klass->parent)); /*So hitting this assert is a huge problem*/
4997 for (i = 0; i < klass->parent->method.count; i++) {
4998 MonoMethod *m = klass->parent->methods [i];
4999 if (!strncmp (m->name, "InternalArray__", 15)) {
5001 list = g_list_prepend (list, m);
5004 list = g_list_reverse (list);
5005 generic_array_method_info = (GenericArrayMethodInfo *)mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
5007 for (tmp = list; tmp; tmp = tmp->next) {
5008 const char *mname, *iname;
5010 MonoMethod *m = (MonoMethod *)tmp->data;
5011 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
5012 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
5014 generic_array_method_info [i].array_method = m;
5015 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
5016 iname = "System.Collections.Generic.ICollection`1.";
5017 mname = m->name + 27;
5018 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
5019 iname = "System.Collections.Generic.IEnumerable`1.";
5020 mname = m->name + 27;
5021 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
5022 iname = "System.Collections.Generic.IReadOnlyList`1.";
5023 mname = m->name + strlen (ireadonlylist_prefix);
5024 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
5025 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
5026 mname = m->name + strlen (ireadonlycollection_prefix);
5027 } else if (!strncmp (m->name, "InternalArray__", 15)) {
5028 iname = "System.Collections.Generic.IList`1.";
5029 mname = m->name + 15;
5031 g_assert_not_reached ();
5034 name = (gchar *)mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
5035 strcpy (name, iname);
5036 strcpy (name + strlen (iname), mname);
5037 generic_array_method_info [i].name = name;
5040 /*g_print ("array generic methods: %d\n", count_generic);*/
5042 generic_array_method_num = count_generic;
5044 return generic_array_method_num;
5048 setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos)
5050 MonoGenericContext tmp_context;
5053 tmp_context.class_inst = NULL;
5054 tmp_context.method_inst = mono_class_get_generic_class (iface)->context.class_inst;
5055 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
5057 for (i = 0; i < generic_array_method_num; i++) {
5059 MonoMethod *m = generic_array_method_info [i].array_method;
5060 MonoMethod *inflated;
5062 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
5063 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
5064 methods [pos++] = mono_marshal_get_generic_array_helper (klass, iface, generic_array_method_info [i].name, inflated);
5069 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
5071 int null_length = strlen ("(null)");
5072 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
5073 char *s = (char *)mono_image_alloc (image, len);
5076 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
5077 g_assert (result == len - 1);
5084 * @klass: the class to initialize
5086 * Compute the instance_size, class_size and other infos that cannot be
5087 * computed at mono_class_get() time. Also compute vtable_size if possible.
5088 * Returns TRUE on success or FALSE if there was a problem in loading
5089 * the type (incorrect assemblies, missing assemblies, methods, etc).
5090 * Initializes the following fields in @klass:
5091 * - all the fields initialized by mono_class_init_sizes ()
5096 * LOCKING: Acquires the loader lock.
5099 mono_class_init (MonoClass *klass)
5101 int i, vtable_size = 0, array_method_count = 0;
5102 MonoCachedClassInfo cached_info;
5103 gboolean has_cached_info;
5104 gboolean locked = FALSE;
5105 gboolean ghcimpl = FALSE;
5106 gboolean has_cctor = FALSE;
5107 int first_iface_slot = 0;
5111 /* Double-checking locking pattern */
5112 if (klass->inited || mono_class_has_failure (klass))
5113 return !mono_class_has_failure (klass);
5115 /*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/
5118 * This function can recursively call itself.
5120 GSList *init_list = (GSList *)mono_native_tls_get_value (init_pending_tls_id);
5121 if (g_slist_find (init_list, klass)) {
5122 mono_class_set_type_load_failure (klass, "Recursive type definition detected");
5125 init_list = g_slist_prepend (init_list, klass);
5126 mono_native_tls_set_value (init_pending_tls_id, init_list);
5129 * We want to avoid doing complicated work inside locks, so we compute all the required
5130 * information and write it to @klass inside a lock.
5133 if (mono_verifier_is_enabled_for_class (klass) && !mono_verifier_verify_class (klass)) {
5134 mono_class_set_type_load_failure (klass, "%s", concat_two_strings_with_zero (klass->image, klass->name, klass->image->assembly_name));
5138 if (klass->byval_arg.type == MONO_TYPE_ARRAY || klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5139 MonoClass *element_class = klass->element_class;
5140 if (!element_class->inited)
5141 mono_class_init (element_class);
5142 if (mono_class_set_type_load_failure_causedby_class (klass, element_class, "Could not load array element class"))
5146 mono_stats.initialized_class_count++;
5148 if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic) {
5149 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5151 mono_class_init (gklass);
5152 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic Type Definition failed to init"))
5155 mono_class_setup_interface_id (klass);
5158 if (klass->parent && !klass->parent->inited)
5159 mono_class_init (klass->parent);
5161 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
5163 /* Compute instance size etc. */
5164 init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
5165 if (mono_class_has_failure (klass))
5168 mono_class_setup_supertypes (klass);
5171 initialize_object_slots (klass);
5174 * Initialize the rest of the data without creating a generic vtable if possible.
5175 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5176 * also avoid computing a generic vtable.
5178 if (has_cached_info) {
5180 vtable_size = cached_info.vtable_size;
5181 ghcimpl = cached_info.ghcimpl;
5182 has_cctor = cached_info.has_cctor;
5183 } else if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5184 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5185 * The first slot if for array with.
5187 static int szarray_vtable_size[2] = { 0 };
5189 int slot = MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg) ? 0 : 1;
5192 if (!szarray_vtable_size [slot]) {
5193 mono_class_setup_vtable (klass);
5194 szarray_vtable_size [slot] = klass->vtable_size;
5195 vtable_size = klass->vtable_size;
5197 vtable_size = szarray_vtable_size[slot];
5199 } else if (mono_class_is_ginst (klass) && !MONO_CLASS_IS_INTERFACE (klass)) {
5200 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5202 /* Generic instance case */
5203 ghcimpl = gklass->ghcimpl;
5204 has_cctor = gklass->has_cctor;
5206 mono_class_setup_vtable (gklass);
5207 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to init"))
5210 vtable_size = gklass->vtable_size;
5214 /* ghcimpl is not currently used
5216 if (klass->parent) {
5217 MonoMethod *cmethod = klass->vtable [ghc_slot];
5218 if (cmethod->is_inflated)
5219 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5220 if (cmethod == default_ghc) {
5226 /* C# doesn't allow interfaces to have cctors */
5227 if (!MONO_CLASS_IS_INTERFACE (klass) || klass->image != mono_defaults.corlib) {
5228 MonoMethod *cmethod = NULL;
5230 if (mono_class_is_ginst (klass)) {
5231 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5233 /* Generic instance case */
5234 ghcimpl = gklass->ghcimpl;
5235 has_cctor = gklass->has_cctor;
5236 } else if (klass->type_token && !image_is_dynamic(klass->image)) {
5237 cmethod = find_method_in_metadata (klass, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5238 /* The find_method function ignores the 'flags' argument */
5239 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5242 mono_class_setup_methods (klass);
5243 if (mono_class_has_failure (klass))
5246 for (i = 0; i < klass->method.count; ++i) {
5247 MonoMethod *method = klass->methods [i];
5248 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5249 (strcmp (".cctor", method->name) == 0)) {
5259 array_method_count = 3 + (klass->rank > 1? 2: 1);
5261 if (klass->interface_count) {
5262 int count_generic = generic_array_methods (klass);
5263 array_method_count += klass->interface_count * count_generic;
5267 if (klass->parent) {
5268 if (!klass->parent->vtable_size)
5269 mono_class_setup_vtable (klass->parent);
5270 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class vtable failed to initialize"))
5272 g_assert (klass->parent->vtable_size);
5273 first_iface_slot = klass->parent->vtable_size;
5274 if (mono_class_need_stelemref_method (klass))
5279 * Do the actual changes to @klass inside the loader lock
5281 mono_loader_lock ();
5284 if (klass->inited || mono_class_has_failure (klass)) {
5285 mono_loader_unlock ();
5286 /* Somebody might have gotten in before us */
5287 return !mono_class_has_failure (klass);
5290 mono_stats.initialized_class_count++;
5292 if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic) {
5293 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5295 mono_stats.generic_class_count++;
5297 klass->method = gklass->method;
5298 klass->field = gklass->field;
5301 if (mono_class_is_ginst (klass) || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
5302 klass->nested_classes_inited = TRUE;
5303 klass->ghcimpl = ghcimpl;
5304 klass->has_cctor = has_cctor;
5306 klass->vtable_size = vtable_size;
5307 if (has_cached_info) {
5308 klass->has_finalize = cached_info.has_finalize;
5309 klass->has_finalize_inited = TRUE;
5312 klass->method.count = array_method_count;
5314 mono_loader_unlock ();
5317 setup_interface_offsets (klass, first_iface_slot, TRUE);
5319 if (mono_security_core_clr_enabled ())
5320 mono_security_core_clr_check_inheritance (klass);
5322 if (mono_class_is_ginst (klass) && !mono_verifier_class_is_valid_generic_instantiation (klass))
5323 mono_class_set_type_load_failure (klass, "Invalid generic instantiation");
5328 init_list = g_slist_remove (init_list, klass);
5329 mono_native_tls_set_value (init_pending_tls_id, init_list);
5331 /* Because of the double-checking locking pattern */
5332 mono_memory_barrier ();
5336 mono_loader_unlock ();
5338 return !mono_class_has_failure (klass);
5342 * mono_class_has_finalizer:
5344 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5348 mono_class_has_finalizer (MonoClass *klass)
5350 gboolean has_finalize = FALSE;
5352 if (klass->has_finalize_inited)
5353 return klass->has_finalize;
5355 /* Interfaces and valuetypes are not supposed to have finalizers */
5356 if (!(MONO_CLASS_IS_INTERFACE (klass) || klass->valuetype)) {
5357 MonoMethod *cmethod = NULL;
5359 if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5360 } else if (mono_class_is_ginst (klass)) {
5361 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5363 has_finalize = mono_class_has_finalizer (gklass);
5364 } else if (klass->parent && klass->parent->has_finalize) {
5365 has_finalize = TRUE;
5367 if (klass->parent) {
5369 * Can't search in metadata for a method named Finalize, because that
5370 * ignores overrides.
5372 mono_class_setup_vtable (klass);
5373 if (mono_class_has_failure (klass))
5376 cmethod = klass->vtable [finalize_slot];
5380 g_assert (klass->vtable_size > finalize_slot);
5382 if (klass->parent) {
5383 if (cmethod->is_inflated)
5384 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5385 if (cmethod != default_finalize)
5386 has_finalize = TRUE;
5392 mono_image_lock (klass->image);
5394 if (!klass->has_finalize_inited) {
5395 klass->has_finalize = has_finalize ? 1 : 0;
5397 mono_memory_barrier ();
5398 klass->has_finalize_inited = TRUE;
5401 mono_image_unlock (klass->image);
5403 return klass->has_finalize;
5407 mono_is_corlib_image (MonoImage *image)
5409 return image == mono_defaults.corlib;
5413 * LOCKING: this assumes the loader lock is held
5416 mono_class_setup_mono_type (MonoClass *klass)
5418 const char *name = klass->name;
5419 const char *nspace = klass->name_space;
5420 gboolean is_corlib = mono_is_corlib_image (klass->image);
5422 klass->this_arg.byref = 1;
5423 klass->this_arg.data.klass = klass;
5424 klass->this_arg.type = MONO_TYPE_CLASS;
5425 klass->byval_arg.data.klass = klass;
5426 klass->byval_arg.type = MONO_TYPE_CLASS;
5428 if (is_corlib && !strcmp (nspace, "System")) {
5429 if (!strcmp (name, "ValueType")) {
5431 * do not set the valuetype bit for System.ValueType.
5432 * klass->valuetype = 1;
5434 klass->blittable = TRUE;
5435 } else if (!strcmp (name, "Enum")) {
5437 * do not set the valuetype bit for System.Enum.
5438 * klass->valuetype = 1;
5440 klass->valuetype = 0;
5441 klass->enumtype = 0;
5442 } else if (!strcmp (name, "Object")) {
5443 klass->byval_arg.type = MONO_TYPE_OBJECT;
5444 klass->this_arg.type = MONO_TYPE_OBJECT;
5445 } else if (!strcmp (name, "String")) {
5446 klass->byval_arg.type = MONO_TYPE_STRING;
5447 klass->this_arg.type = MONO_TYPE_STRING;
5448 } else if (!strcmp (name, "TypedReference")) {
5449 klass->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5450 klass->this_arg.type = MONO_TYPE_TYPEDBYREF;
5454 if (klass->valuetype) {
5455 int t = MONO_TYPE_VALUETYPE;
5457 if (is_corlib && !strcmp (nspace, "System")) {
5460 if (!strcmp (name, "Boolean")) {
5461 t = MONO_TYPE_BOOLEAN;
5462 } else if (!strcmp(name, "Byte")) {
5464 klass->blittable = TRUE;
5468 if (!strcmp (name, "Char")) {
5473 if (!strcmp (name, "Double")) {
5475 klass->blittable = TRUE;
5479 if (!strcmp (name, "Int32")) {
5481 klass->blittable = TRUE;
5482 } else if (!strcmp(name, "Int16")) {
5484 klass->blittable = TRUE;
5485 } else if (!strcmp(name, "Int64")) {
5487 klass->blittable = TRUE;
5488 } else if (!strcmp(name, "IntPtr")) {
5490 klass->blittable = TRUE;
5494 if (!strcmp (name, "Single")) {
5496 klass->blittable = TRUE;
5497 } else if (!strcmp(name, "SByte")) {
5499 klass->blittable = TRUE;
5503 if (!strcmp (name, "UInt32")) {
5505 klass->blittable = TRUE;
5506 } else if (!strcmp(name, "UInt16")) {
5508 klass->blittable = TRUE;
5509 } else if (!strcmp(name, "UInt64")) {
5511 klass->blittable = TRUE;
5512 } else if (!strcmp(name, "UIntPtr")) {
5514 klass->blittable = TRUE;
5518 if (!strcmp (name, "TypedReference")) {
5519 t = MONO_TYPE_TYPEDBYREF;
5520 klass->blittable = TRUE;
5524 if (!strcmp (name, "Void")) {
5532 klass->byval_arg.type = (MonoTypeEnum)t;
5533 klass->this_arg.type = (MonoTypeEnum)t;
5536 if (MONO_CLASS_IS_INTERFACE (klass))
5537 klass->interface_id = mono_get_unique_iid (klass);
5542 * COM initialization is delayed until needed.
5543 * However when a [ComImport] attribute is present on a type it will trigger
5544 * the initialization. This is not a problem unless the BCL being executed
5545 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5548 init_com_from_comimport (MonoClass *klass)
5550 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5551 if (mono_security_core_clr_enabled ()) {
5552 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5553 if (!mono_security_core_clr_determine_platform_image (klass->image)) {
5554 /* but it can not be made available for application (i.e. user code) since all COM calls
5555 * are considered native calls. In this case we fail with a TypeLoadException (just like
5556 * Silverlight 2 does */
5557 mono_class_set_type_load_failure (klass, "");
5562 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5564 #endif /*DISABLE_COM*/
5567 * LOCKING: this assumes the loader lock is held
5570 mono_class_setup_parent (MonoClass *klass, MonoClass *parent)
5572 gboolean system_namespace;
5573 gboolean is_corlib = mono_is_corlib_image (klass->image);
5575 system_namespace = !strcmp (klass->name_space, "System") && is_corlib;
5577 /* if root of the hierarchy */
5578 if (system_namespace && !strcmp (klass->name, "Object")) {
5579 klass->parent = NULL;
5580 klass->instance_size = sizeof (MonoObject);
5583 if (!strcmp (klass->name, "<Module>")) {
5584 klass->parent = NULL;
5585 klass->instance_size = 0;
5589 if (!MONO_CLASS_IS_INTERFACE (klass)) {
5590 /* Imported COM Objects always derive from __ComObject. */
5592 if (MONO_CLASS_IS_IMPORT (klass)) {
5593 init_com_from_comimport (klass);
5594 if (parent == mono_defaults.object_class)
5595 parent = mono_class_get_com_object_class ();
5599 /* set the parent to something useful and safe, but mark the type as broken */
5600 parent = mono_defaults.object_class;
5601 mono_class_set_type_load_failure (klass, "");
5605 klass->parent = parent;
5607 if (mono_class_is_ginst (parent) && !parent->name) {
5609 * If the parent is a generic instance, we may get
5610 * called before it is fully initialized, especially
5611 * before it has its name.
5616 #ifndef DISABLE_REMOTING
5617 klass->marshalbyref = parent->marshalbyref;
5618 klass->contextbound = parent->contextbound;
5621 klass->delegate = parent->delegate;
5623 if (MONO_CLASS_IS_IMPORT (klass) || mono_class_is_com_object (parent))
5624 mono_class_set_is_com_object (klass);
5626 if (system_namespace) {
5627 #ifndef DISABLE_REMOTING
5628 if (klass->name [0] == 'M' && !strcmp (klass->name, "MarshalByRefObject"))
5629 klass->marshalbyref = 1;
5631 if (klass->name [0] == 'C' && !strcmp (klass->name, "ContextBoundObject"))
5632 klass->contextbound = 1;
5634 if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate"))
5635 klass->delegate = 1;
5638 if (klass->parent->enumtype || (mono_is_corlib_image (klass->parent->image) && (strcmp (klass->parent->name, "ValueType") == 0) &&
5639 (strcmp (klass->parent->name_space, "System") == 0)))
5640 klass->valuetype = 1;
5641 if (mono_is_corlib_image (klass->parent->image) && ((strcmp (klass->parent->name, "Enum") == 0) && (strcmp (klass->parent->name_space, "System") == 0))) {
5642 klass->valuetype = klass->enumtype = 1;
5644 /*klass->enumtype = klass->parent->enumtype; */
5646 /* initialize com types if COM interfaces are present */
5648 if (MONO_CLASS_IS_IMPORT (klass))
5649 init_com_from_comimport (klass);
5651 klass->parent = NULL;
5657 * mono_class_setup_supertypes:
5660 * Build the data structure needed to make fast type checks work.
5661 * This currently sets two fields in @class:
5662 * - idepth: distance between @class and System.Object in the type
5664 * - supertypes: array of classes: each element has a class in the hierarchy
5665 * starting from @class up to System.Object
5667 * LOCKING: This function is atomic, in case of contention we waste memory.
5670 mono_class_setup_supertypes (MonoClass *klass)
5673 MonoClass **supertypes;
5675 mono_atomic_load_acquire (supertypes, MonoClass **, &klass->supertypes);
5679 if (klass->parent && !klass->parent->supertypes)
5680 mono_class_setup_supertypes (klass->parent);
5682 klass->idepth = klass->parent->idepth + 1;
5686 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, klass->idepth);
5687 supertypes = (MonoClass **)mono_class_alloc0 (klass, sizeof (MonoClass *) * ms);
5689 if (klass->parent) {
5690 CHECKED_METADATA_WRITE_PTR ( supertypes [klass->idepth - 1] , klass );
5693 for (supertype_idx = 0; supertype_idx < klass->parent->idepth; supertype_idx++)
5694 CHECKED_METADATA_WRITE_PTR ( supertypes [supertype_idx] , klass->parent->supertypes [supertype_idx] );
5696 CHECKED_METADATA_WRITE_PTR ( supertypes [0] , klass );
5699 CHECKED_METADATA_WRITE_PTR_ATOMIC ( klass->supertypes , supertypes );
5703 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5705 MonoClass *gtd = (MonoClass*)user_data;
5706 /* Only try to fix generic instances of @gtd */
5707 if (mono_class_get_generic_class (gclass)->container_class != gtd)
5710 /* Check if the generic instance has no parent. */
5711 if (gtd->parent && !gclass->parent)
5712 mono_generic_class_setup_parent (gclass, gtd);
5718 mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char *msg)
5720 mono_class_set_type_load_failure (klass, "%s", msg);
5721 mono_error_set_type_load_class (error, klass, "%s", msg);
5725 * mono_class_create_from_typedef:
5726 * @image: image where the token is valid
5727 * @type_token: typedef token
5728 * @error: used to return any error found while creating the type
5730 * Create the MonoClass* representing the specified type token.
5731 * @type_token must be a TypeDef token.
5733 * FIXME: don't return NULL on failure, just the the caller figure it out.
5736 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5738 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5739 MonoClass *klass, *parent = NULL;
5740 guint32 cols [MONO_TYPEDEF_SIZE];
5741 guint32 cols_next [MONO_TYPEDEF_SIZE];
5742 guint tidx = mono_metadata_token_index (type_token);
5743 MonoGenericContext *context = NULL;
5744 const char *name, *nspace;
5746 MonoClass **interfaces;
5747 guint32 field_last, method_last;
5748 guint32 nesting_tokeen;
5750 mono_error_init (error);
5752 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5753 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5757 mono_loader_lock ();
5759 if ((klass = (MonoClass *)mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5760 mono_loader_unlock ();
5764 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5766 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5767 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5769 if (mono_metadata_has_generic_params (image, type_token)) {
5770 klass = mono_image_alloc0 (image, sizeof (MonoClassGtd));
5771 klass->class_kind = MONO_CLASS_GTD;
5772 classes_size += sizeof (MonoClassGtd);
5775 klass = mono_image_alloc0 (image, sizeof (MonoClassDef));
5776 klass->class_kind = MONO_CLASS_DEF;
5777 classes_size += sizeof (MonoClassDef);
5782 klass->name_space = nspace;
5784 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5786 klass->image = image;
5787 klass->type_token = type_token;
5788 mono_class_set_flags (klass, cols [MONO_TYPEDEF_FLAGS]);
5790 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
5793 * Check whether we're a generic type definition.
5795 if (mono_class_is_gtd (klass)) {
5796 MonoGenericContainer *generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
5797 generic_container->owner.klass = klass;
5798 generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
5799 context = &generic_container->context;
5800 mono_class_set_generic_container (klass, generic_container);
5801 enable_gclass_recording ();
5804 if (cols [MONO_TYPEDEF_EXTENDS]) {
5806 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5808 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5809 /*WARNING: this must satisfy mono_metadata_type_hash*/
5810 klass->this_arg.byref = 1;
5811 klass->this_arg.data.klass = klass;
5812 klass->this_arg.type = MONO_TYPE_CLASS;
5813 klass->byval_arg.data.klass = klass;
5814 klass->byval_arg.type = MONO_TYPE_CLASS;
5816 parent = mono_class_get_checked (image, parent_token, error);
5817 if (parent && context) /* Always inflate */
5818 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5820 if (parent == NULL) {
5821 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5822 goto parent_failure;
5825 for (tmp = parent; tmp; tmp = tmp->parent) {
5827 mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
5828 goto parent_failure;
5830 if (mono_class_is_gtd (klass) && mono_class_is_ginst (tmp) && mono_class_get_generic_class (tmp)->container_class == klass) {
5831 mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
5832 goto parent_failure;
5837 mono_class_setup_parent (klass, parent);
5839 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5840 mono_class_setup_mono_type (klass);
5842 if (mono_class_is_gtd (klass))
5843 disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
5846 * This might access klass->byval_arg for recursion generated by generic constraints,
5847 * so it has to come after setup_mono_type ().
5849 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5850 klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5851 if (!mono_error_ok (error)) {
5852 /*FIXME implement a mono_class_set_failure_from_mono_error */
5853 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5854 mono_loader_unlock ();
5855 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5860 if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5864 if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5868 klass->cast_class = klass->element_class = klass;
5870 if (!klass->enumtype) {
5871 if (!mono_metadata_interfaces_from_typedef_full (
5872 image, type_token, &interfaces, &icount, FALSE, context, error)){
5874 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5875 mono_loader_unlock ();
5876 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5880 /* This is required now that it is possible for more than 2^16 interfaces to exist. */
5881 g_assert(icount <= 65535);
5883 klass->interfaces = interfaces;
5884 klass->interface_count = icount;
5885 klass->interfaces_inited = 1;
5888 /*g_print ("Load class %s\n", name);*/
5891 * Compute the field and method lists
5893 int first_field_idx = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5894 mono_class_set_first_field_idx (klass, first_field_idx);
5895 int first_method_idx = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5896 mono_class_set_first_method_idx (klass, first_method_idx);
5898 if (tt->rows > tidx){
5899 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5900 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5901 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5903 field_last = image->tables [MONO_TABLE_FIELD].rows;
5904 method_last = image->tables [MONO_TABLE_METHOD].rows;
5907 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5908 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5909 klass->field.count = field_last - first_field_idx;
5911 klass->field.count = 0;
5913 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5914 klass->method.count = method_last - first_method_idx;
5916 klass->method.count = 0;
5918 /* reserve space to store vector pointer in arrays */
5919 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5920 klass->instance_size += 2 * sizeof (gpointer);
5921 g_assert (klass->field.count == 0);
5924 if (klass->enumtype) {
5925 MonoType *enum_basetype = mono_class_find_enum_basetype (klass, error);
5926 if (!enum_basetype) {
5927 /*set it to a default value as the whole runtime can't handle this to be null*/
5928 klass->cast_class = klass->element_class = mono_defaults.int32_class;
5929 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5930 mono_loader_unlock ();
5931 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5934 klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
5938 * If we're a generic type definition, load the constraints.
5939 * We must do this after the class has been constructed to make certain recursive scenarios
5942 if (mono_class_is_gtd (klass) && !mono_metadata_load_generic_param_constraints_checked (image, type_token, mono_class_get_generic_container (klass), error)) {
5943 mono_class_set_type_load_failure (klass, "Could not load generic parameter constrains due to %s", mono_error_get_message (error));
5944 mono_loader_unlock ();
5945 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5949 if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5950 if (!strncmp (name, "Vector", 6))
5951 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");
5954 mono_loader_unlock ();
5956 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5961 mono_class_setup_mono_type (klass);
5962 mono_loader_unlock ();
5963 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5967 /** Is klass a Nullable<T> ginst? */
5969 mono_class_is_nullable (MonoClass *klass)
5971 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
5972 return gklass && gklass->container_class == mono_defaults.generic_nullable_class;
5976 /** if klass is T? return T */
5978 mono_class_get_nullable_param (MonoClass *klass)
5980 g_assert (mono_class_is_nullable (klass));
5981 return mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
5985 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5989 MonoGenericClass *gclass = mono_class_get_generic_class (klass);
5991 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5992 if (!mono_error_ok (&error)) {
5993 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5994 klass->parent = mono_defaults.object_class;
5995 mono_class_set_type_load_failure (klass, "Parent is a generic type instantiation that failed due to: %s", mono_error_get_message (&error));
5996 mono_error_cleanup (&error);
6000 mono_class_setup_parent (klass, klass->parent);
6002 if (klass->enumtype) {
6003 klass->cast_class = gtd->cast_class;
6004 klass->element_class = gtd->element_class;
6010 * Create the `MonoClass' for an instantiation of a generic type.
6011 * We only do this if we actually need it.
6014 mono_generic_class_get_class (MonoGenericClass *gclass)
6016 MonoClass *klass, *gklass;
6018 if (gclass->cached_class)
6019 return gclass->cached_class;
6021 mono_loader_lock ();
6022 if (gclass->cached_class) {
6023 mono_loader_unlock ();
6024 return gclass->cached_class;
6027 klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClassGenericInst));
6029 gklass = gclass->container_class;
6031 if (record_gclass_instantiation > 0)
6032 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
6034 if (gklass->nested_in) {
6035 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
6036 klass->nested_in = gklass->nested_in;
6039 klass->name = gklass->name;
6040 klass->name_space = gklass->name_space;
6042 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6044 klass->image = gklass->image;
6045 klass->type_token = gklass->type_token;
6046 klass->field.count = gklass->field.count;
6048 klass->class_kind = MONO_CLASS_GINST;
6050 ((MonoClassGenericInst*)klass)->generic_class = gclass;
6052 klass->byval_arg.type = MONO_TYPE_GENERICINST;
6053 klass->this_arg.type = klass->byval_arg.type;
6054 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
6055 klass->this_arg.byref = TRUE;
6056 klass->enumtype = gklass->enumtype;
6057 klass->valuetype = gklass->valuetype;
6059 klass->cast_class = klass->element_class = klass;
6061 if (mono_class_is_nullable (klass))
6062 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
6065 * We're not interested in the nested classes of a generic instance.
6066 * We use the generic type definition to look for nested classes.
6069 mono_generic_class_setup_parent (klass, gklass);
6071 if (gclass->is_dynamic) {
6073 * 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.
6074 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
6075 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
6077 if (!gklass->wastypebuilder)
6080 mono_class_setup_supertypes (klass);
6082 if (klass->enumtype) {
6084 * For enums, gklass->fields might not been set, but instance_size etc. is
6085 * already set in mono_reflection_create_internal_class (). For non-enums,
6086 * these will be computed normally in mono_class_layout_fields ().
6088 klass->instance_size = gklass->instance_size;
6089 klass->sizes.class_size = gklass->sizes.class_size;
6090 mono_memory_barrier ();
6091 klass->size_inited = 1;
6095 mono_memory_barrier ();
6096 gclass->cached_class = klass;
6098 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6100 ++class_ginst_count;
6101 inflated_classes_size += sizeof (MonoClassGenericInst);
6103 mono_loader_unlock ();
6109 get_image_for_container (MonoGenericContainer *container)
6112 if (container->is_anonymous) {
6113 result = container->owner.image;
6116 if (container->is_method) {
6117 MonoMethod *method = container->owner.method;
6118 g_assert_checked (method);
6119 klass = method->klass;
6121 klass = container->owner.klass;
6123 g_assert_checked (klass);
6124 result = klass->image;
6131 get_image_for_generic_param (MonoGenericParam *param)
6133 MonoGenericContainer *container = mono_generic_param_owner (param);
6134 g_assert_checked (container);
6135 return get_image_for_container (container);
6138 // Make a string in the designated image consisting of a single integer.
6139 #define INT_STRING_SIZE 16
6141 make_generic_name_string (MonoImage *image, int num)
6143 char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
6144 g_snprintf (name, INT_STRING_SIZE, "%d", num);
6148 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
6149 // pinfo is derived from param by the caller for us.
6151 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
6153 MonoClass *klass, **ptr;
6155 MonoGenericContainer *container = mono_generic_param_owner (param);
6156 g_assert_checked (container);
6158 MonoImage *image = get_image_for_container (container);
6159 gboolean is_mvar = container->is_method;
6160 gboolean is_anonymous = container->is_anonymous;
6162 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassGenericParam));
6163 klass->class_kind = MONO_CLASS_GPARAM;
6164 classes_size += sizeof (MonoClassGenericParam);
6165 ++class_gparam_count;
6168 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
6170 int n = mono_generic_param_num (param);
6171 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
6175 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , "" );
6176 } else if (is_mvar) {
6177 MonoMethod *omethod = container->owner.method;
6178 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
6180 MonoClass *oklass = container->owner.klass;
6181 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
6184 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6186 // Count non-NULL items in pinfo->constraints
6189 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6193 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6194 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
6196 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
6197 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
6199 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
6202 if (count - pos > 0) {
6203 klass->interface_count = count - pos;
6204 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
6205 klass->interfaces_inited = TRUE;
6206 for (i = pos; i < count; i++)
6207 CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
6210 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
6212 klass->inited = TRUE;
6213 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class , klass );
6214 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
6216 klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6217 klass->this_arg.type = klass->byval_arg.type;
6218 CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param , param );
6219 CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
6220 klass->this_arg.byref = TRUE;
6222 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6223 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6225 /*Init these fields to sane values*/
6226 klass->min_align = 1;
6228 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6229 * constrained to, the JIT depends on this.
6231 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6232 mono_memory_barrier ();
6233 klass->size_inited = 1;
6235 mono_class_setup_supertypes (klass);
6237 if (count - pos > 0) {
6238 mono_class_setup_vtable (klass->parent);
6239 if (mono_class_has_failure (klass->parent))
6240 mono_class_set_type_load_failure (klass, "Failed to setup parent interfaces");
6242 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6248 #define FAST_CACHE_SIZE 16
6251 * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6252 * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6253 * we cache the MonoClasses.
6254 * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6255 * LOCKING: Takes the image lock depending on @take_lock.
6258 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6260 int n = mono_generic_param_num (param);
6261 MonoImage *image = get_image_for_generic_param (param);
6262 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6263 MonoClass *klass = NULL;
6268 // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6269 // For high numbers or constraints we have to use pointer hashes.
6270 if (param->gshared_constraint) {
6271 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6274 mono_image_lock (image);
6275 klass = (MonoClass *)g_hash_table_lookup (ht, param);
6277 mono_image_unlock (image);
6282 if (n < FAST_CACHE_SIZE) {
6284 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6286 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6288 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6291 mono_image_lock (image);
6292 klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6294 mono_image_unlock (image);
6301 * LOCKING: Image lock (param->image) must be held
6304 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6306 int n = mono_generic_param_num (param);
6307 MonoImage *image = get_image_for_generic_param (param);
6308 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6312 if (param->gshared_constraint) {
6313 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6315 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6316 mono_memory_barrier ();
6318 image->mvar_cache_constrained = ht;
6320 image->var_cache_constrained = ht;
6322 g_hash_table_insert (ht, param, klass);
6323 } else if (n < FAST_CACHE_SIZE) {
6325 /* Requires locking to avoid droping an already published class */
6326 if (!image->mvar_cache_fast)
6327 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6328 image->mvar_cache_fast [n] = klass;
6330 if (!image->var_cache_fast)
6331 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6332 image->var_cache_fast [n] = klass;
6335 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6337 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6339 ht = g_hash_table_new (NULL, NULL);
6340 mono_memory_barrier ();
6342 image->mvar_cache_slow = ht;
6344 image->var_cache_slow = ht;
6347 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6352 * LOCKING: Acquires the image lock (@image).
6355 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6357 MonoImage *image = get_image_for_generic_param (param);
6358 MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6359 MonoClass *klass, *klass2;
6361 // If a klass already exists for this object and is cached, return it.
6362 if (pinfo) // Non-anonymous
6363 klass = pinfo->pklass;
6365 klass = get_anon_gparam_class (param, TRUE);
6370 // Create a new klass
6371 klass = make_generic_param_class (param, pinfo);
6373 // Now we need to cache the klass we created.
6374 // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6375 // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6376 // and allow our newly-created klass object to just leak.
6377 mono_memory_barrier ();
6379 mono_image_lock (image);
6381 // Here "klass2" refers to the klass potentially created by the other thread.
6382 if (pinfo) // Repeat check from above
6383 klass2 = pinfo->pklass;
6385 klass2 = get_anon_gparam_class (param, FALSE);
6392 pinfo->pklass = klass;
6394 set_anon_gparam_class (param, klass);
6396 mono_image_unlock (image);
6398 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6400 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED); // Alert profiler about botched class create
6402 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6408 * mono_class_from_generic_parameter:
6409 * @param: Parameter to find/construct a class for.
6410 * @arg2: Is ignored.
6411 * @arg3: Is ignored.
6414 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6416 return mono_class_from_generic_parameter_internal (param);
6421 mono_ptr_class_get (MonoType *type)
6424 MonoClass *el_class;
6428 el_class = mono_class_from_mono_type (type);
6429 image = el_class->image;
6431 mono_image_lock (image);
6432 if (image->ptr_cache) {
6433 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6434 mono_image_unlock (image);
6438 mono_image_unlock (image);
6440 result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassPointer));
6442 classes_size += sizeof (MonoClassPointer);
6443 ++class_pointer_count;
6445 result->parent = NULL; /* no parent for PTR types */
6446 result->name_space = el_class->name_space;
6447 name = g_strdup_printf ("%s*", el_class->name);
6448 result->name = mono_image_strdup (image, name);
6449 result->class_kind = MONO_CLASS_POINTER;
6452 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6454 result->image = el_class->image;
6455 result->inited = TRUE;
6456 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6457 result->cast_class = result->element_class = el_class;
6458 result->blittable = TRUE;
6460 result->byval_arg.type = MONO_TYPE_PTR;
6461 result->this_arg.type = result->byval_arg.type;
6462 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6463 result->this_arg.byref = TRUE;
6465 mono_class_setup_supertypes (result);
6467 mono_image_lock (image);
6468 if (image->ptr_cache) {
6470 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6471 mono_image_unlock (image);
6472 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6476 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6478 g_hash_table_insert (image->ptr_cache, el_class, result);
6479 mono_image_unlock (image);
6481 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6487 mono_fnptr_class_get (MonoMethodSignature *sig)
6490 static GHashTable *ptr_hash = NULL;
6492 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6494 mono_loader_lock ();
6497 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6499 if ((result = (MonoClass *)g_hash_table_lookup (ptr_hash, sig))) {
6500 mono_loader_unlock ();
6503 result = g_new0 (MonoClass, 1);
6505 classes_size += sizeof (MonoClassPointer);
6506 ++class_pointer_count;
6508 result->parent = NULL; /* no parent for PTR types */
6509 result->name_space = "System";
6510 result->name = "MonoFNPtrFakeClass";
6511 result->class_kind = MONO_CLASS_POINTER;
6513 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6515 result->image = mono_defaults.corlib; /* need to fix... */
6516 result->inited = TRUE;
6517 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6518 result->cast_class = result->element_class = result;
6519 result->blittable = TRUE;
6521 result->byval_arg.type = MONO_TYPE_FNPTR;
6522 result->this_arg.type = result->byval_arg.type;
6523 result->this_arg.data.method = result->byval_arg.data.method = sig;
6524 result->this_arg.byref = TRUE;
6525 result->blittable = TRUE;
6527 mono_class_setup_supertypes (result);
6529 g_hash_table_insert (ptr_hash, sig, result);
6531 mono_loader_unlock ();
6533 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6539 * mono_class_from_mono_type:
6540 * @type: describes the type to return
6542 * This returns a MonoClass for the specified MonoType, the value is never NULL.
6545 mono_class_from_mono_type (MonoType *type)
6547 switch (type->type) {
6548 case MONO_TYPE_OBJECT:
6549 return type->data.klass? type->data.klass: mono_defaults.object_class;
6550 case MONO_TYPE_VOID:
6551 return type->data.klass? type->data.klass: mono_defaults.void_class;
6552 case MONO_TYPE_BOOLEAN:
6553 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6554 case MONO_TYPE_CHAR:
6555 return type->data.klass? type->data.klass: mono_defaults.char_class;
6557 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6559 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6561 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6563 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6565 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6567 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6569 return type->data.klass? type->data.klass: mono_defaults.int_class;
6571 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6573 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6575 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6577 return type->data.klass? type->data.klass: mono_defaults.single_class;
6579 return type->data.klass? type->data.klass: mono_defaults.double_class;
6580 case MONO_TYPE_STRING:
6581 return type->data.klass? type->data.klass: mono_defaults.string_class;
6582 case MONO_TYPE_TYPEDBYREF:
6583 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6584 case MONO_TYPE_ARRAY:
6585 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6587 return mono_ptr_class_get (type->data.type);
6588 case MONO_TYPE_FNPTR:
6589 return mono_fnptr_class_get (type->data.method);
6590 case MONO_TYPE_SZARRAY:
6591 return mono_array_class_get (type->data.klass, 1);
6592 case MONO_TYPE_CLASS:
6593 case MONO_TYPE_VALUETYPE:
6594 return type->data.klass;
6595 case MONO_TYPE_GENERICINST:
6596 return mono_generic_class_get_class (type->data.generic_class);
6597 case MONO_TYPE_MVAR:
6599 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6601 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6602 g_assert_not_reached ();
6605 // Yes, this returns NULL, even if it is documented as not doing so, but there
6606 // is no way for the code to make it this far, due to the assert above.
6611 * mono_type_retrieve_from_typespec
6612 * @image: context where the image is created
6613 * @type_spec: typespec token
6614 * @context: the generic context used to evaluate generic instantiations in
6617 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6619 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6621 *did_inflate = FALSE;
6626 if (context && (context->class_inst || context->method_inst)) {
6627 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6629 if (!mono_error_ok (error)) {
6635 *did_inflate = TRUE;
6642 * mono_class_create_from_typespec
6643 * @image: context where the image is created
6644 * @type_spec: typespec token
6645 * @context: the generic context used to evaluate generic instantiations in
6648 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6651 gboolean inflated = FALSE;
6652 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6653 return_val_if_nok (error, NULL);
6654 ret = mono_class_from_mono_type (t);
6656 mono_metadata_free_type (t);
6661 * mono_bounded_array_class_get:
6662 * @element_class: element class
6663 * @rank: the dimension of the array class
6664 * @bounded: whenever the array has non-zero bounds
6666 * Returns: A class object describing the array with element type @element_type and
6670 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6674 MonoClass *parent = NULL;
6675 GSList *list, *rootlist = NULL;
6679 g_assert (rank <= 255);
6682 /* bounded only matters for one-dimensional arrays */
6685 image = eclass->image;
6687 if (rank == 1 && !bounded) {
6689 * This case is very frequent not just during compilation because of calls
6690 * from mono_class_from_mono_type (), mono_array_new (),
6691 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6693 mono_os_mutex_lock (&image->szarray_cache_lock);
6694 if (!image->szarray_cache)
6695 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6696 klass = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6697 mono_os_mutex_unlock (&image->szarray_cache_lock);
6701 mono_loader_lock ();
6703 mono_loader_lock ();
6705 if (!image->array_cache)
6706 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6708 if ((rootlist = list = (GSList *)g_hash_table_lookup (image->array_cache, eclass))) {
6709 for (; list; list = list->next) {
6710 klass = (MonoClass *)list->data;
6711 if ((klass->rank == rank) && (klass->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6712 mono_loader_unlock ();
6719 parent = mono_defaults.array_class;
6720 if (!parent->inited)
6721 mono_class_init (parent);
6723 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassArray));
6725 klass->image = image;
6726 klass->name_space = eclass->name_space;
6727 klass->class_kind = MONO_CLASS_ARRAY;
6729 nsize = strlen (eclass->name);
6730 name = (char *)g_malloc (nsize + 2 + rank + 1);
6731 memcpy (name, eclass->name, nsize);
6734 memset (name + nsize + 1, ',', rank - 1);
6736 name [nsize + rank] = '*';
6737 name [nsize + rank + bounded] = ']';
6738 name [nsize + rank + bounded + 1] = 0;
6739 klass->name = mono_image_strdup (image, name);
6742 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6744 classes_size += sizeof (MonoClassArray);
6745 ++class_array_count;
6747 klass->type_token = 0;
6748 klass->parent = parent;
6749 klass->instance_size = mono_class_instance_size (klass->parent);
6751 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6752 /*Arrays of those two types are invalid.*/
6753 MonoError prepared_error;
6754 mono_error_init (&prepared_error);
6755 mono_error_set_invalid_program (&prepared_error, "Arrays of void or System.TypedReference types are invalid.");
6756 mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6757 mono_error_cleanup (&prepared_error);
6758 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6759 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6760 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6761 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6763 /* element_size -1 is ok as this is not an instantitable type*/
6764 klass->sizes.element_size = -1;
6766 klass->sizes.element_size = mono_class_array_element_size (eclass);
6768 mono_class_setup_supertypes (klass);
6770 if (mono_class_is_ginst (eclass))
6771 mono_class_init (eclass);
6772 if (!eclass->size_inited)
6773 mono_class_setup_fields (eclass);
6774 mono_class_set_type_load_failure_causedby_class (klass, eclass, "Could not load array element type");
6775 /*FIXME we fail the array type, but we have to let other fields be set.*/
6777 klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6781 if (eclass->enumtype)
6782 klass->cast_class = eclass->element_class;
6784 klass->cast_class = eclass;
6786 switch (klass->cast_class->byval_arg.type) {
6788 klass->cast_class = mono_defaults.byte_class;
6791 klass->cast_class = mono_defaults.int16_class;
6794 #if SIZEOF_VOID_P == 4
6798 klass->cast_class = mono_defaults.int32_class;
6801 #if SIZEOF_VOID_P == 8
6805 klass->cast_class = mono_defaults.int64_class;
6811 klass->element_class = eclass;
6813 if ((rank > 1) || bounded) {
6814 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6815 klass->byval_arg.type = MONO_TYPE_ARRAY;
6816 klass->byval_arg.data.array = at;
6817 at->eklass = eclass;
6819 /* FIXME: complete.... */
6821 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6822 klass->byval_arg.data.klass = eclass;
6824 klass->this_arg = klass->byval_arg;
6825 klass->this_arg.byref = 1;
6827 //WTF was this? it's wrong
6828 // klass->generic_container = eclass->generic_container;
6830 if (rank == 1 && !bounded) {
6831 MonoClass *prev_class;
6833 mono_os_mutex_lock (&image->szarray_cache_lock);
6834 prev_class = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6836 /* Someone got in before us */
6839 g_hash_table_insert (image->szarray_cache, eclass, klass);
6840 mono_os_mutex_unlock (&image->szarray_cache_lock);
6842 list = g_slist_append (rootlist, klass);
6843 g_hash_table_insert (image->array_cache, eclass, list);
6846 mono_loader_unlock ();
6848 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6854 * mono_array_class_get:
6855 * @element_class: element class
6856 * @rank: the dimension of the array class
6858 * Returns: A class object describing the array with element type @element_type and
6862 mono_array_class_get (MonoClass *eclass, guint32 rank)
6864 return mono_bounded_array_class_get (eclass, rank, FALSE);
6868 * mono_class_instance_size:
6871 * Use to get the size of a class in bytes.
6873 * Returns: The size of an object instance
6876 mono_class_instance_size (MonoClass *klass)
6878 if (!klass->size_inited)
6879 mono_class_init (klass);
6881 return klass->instance_size;
6885 * mono_class_min_align:
6888 * Use to get the computed minimum alignment requirements for the specified class.
6890 * Returns: minimum alignment requirements
6893 mono_class_min_align (MonoClass *klass)
6895 if (!klass->size_inited)
6896 mono_class_init (klass);
6898 return klass->min_align;
6902 * mono_class_value_size:
6905 * This function is used for value types, and return the
6906 * space and the alignment to store that kind of value object.
6908 * Returns: the size of a value of kind @klass
6911 mono_class_value_size (MonoClass *klass, guint32 *align)
6915 /* fixme: check disable, because we still have external revereces to
6916 * mscorlib and Dummy Objects
6918 /*g_assert (klass->valuetype);*/
6920 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6923 *align = klass->min_align;
6929 * mono_class_data_size:
6932 * Returns: The size of the static class data
6935 mono_class_data_size (MonoClass *klass)
6938 mono_class_init (klass);
6939 /* This can happen with dynamically created types */
6940 if (!klass->fields_inited)
6941 mono_class_setup_fields (klass);
6943 /* in arrays, sizes.class_size is unioned with element_size
6944 * and arrays have no static fields
6948 return klass->sizes.class_size;
6952 * Auxiliary routine to mono_class_get_field
6954 * Takes a field index instead of a field token.
6956 static MonoClassField *
6957 mono_class_get_field_idx (MonoClass *klass, int idx)
6959 mono_class_setup_fields (klass);
6960 if (mono_class_has_failure (klass))
6964 int first_field_idx = mono_class_get_first_field_idx (klass);
6965 if (klass->image->uncompressed_metadata) {
6967 * first_field_idx points to the FieldPtr table, while idx points into the
6968 * Field table, so we have to do a search.
6970 /*FIXME this is broken for types with multiple fields with the same name.*/
6971 const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6974 for (i = 0; i < klass->field.count; ++i)
6975 if (mono_field_get_name (&klass->fields [i]) == name)
6976 return &klass->fields [i];
6977 g_assert_not_reached ();
6979 if (klass->field.count) {
6980 if ((idx >= first_field_idx) && (idx < first_field_idx + klass->field.count)){
6981 return &klass->fields [idx - first_field_idx];
6985 klass = klass->parent;
6991 * mono_class_get_field:
6992 * @class: the class to lookup the field.
6993 * @field_token: the field token
6995 * Returns: A MonoClassField representing the type and offset of
6996 * the field, or a NULL value if the field does not belong to this
7000 mono_class_get_field (MonoClass *klass, guint32 field_token)
7002 int idx = mono_metadata_token_index (field_token);
7004 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
7006 return mono_class_get_field_idx (klass, idx - 1);
7010 * mono_class_get_field_from_name:
7011 * @klass: the class to lookup the field.
7012 * @name: the field name
7014 * Search the class @klass and it's parents for a field with the name @name.
7016 * Returns: The MonoClassField pointer of the named field or NULL
7019 mono_class_get_field_from_name (MonoClass *klass, const char *name)
7021 return mono_class_get_field_from_name_full (klass, name, NULL);
7025 * mono_class_get_field_from_name_full:
7026 * @klass: the class to lookup the field.
7027 * @name: the field name
7028 * @type: the type of the fields. This optional.
7030 * Search the class @klass and it's parents for a field with the name @name and type @type.
7032 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
7033 * of its generic type definition.
7035 * Returns: The MonoClassField pointer of the named field or NULL
7038 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
7042 mono_class_setup_fields (klass);
7043 if (mono_class_has_failure (klass))
7047 for (i = 0; i < klass->field.count; ++i) {
7048 MonoClassField *field = &klass->fields [i];
7050 if (strcmp (name, mono_field_get_name (field)) != 0)
7054 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
7055 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
7060 klass = klass->parent;
7066 * mono_class_get_field_token:
7067 * @field: the field we need the token of
7069 * Get the token of a field. Note that the tokesn is only valid for the image
7070 * the field was loaded from. Don't use this function for fields in dynamic types.
7072 * Returns: The token representing the field in the image it was loaded from.
7075 mono_class_get_field_token (MonoClassField *field)
7077 MonoClass *klass = field->parent;
7080 mono_class_setup_fields (klass);
7085 int first_field_idx = mono_class_get_first_field_idx (klass);
7086 for (i = 0; i < klass->field.count; ++i) {
7087 if (&klass->fields [i] == field) {
7088 int idx = first_field_idx + i + 1;
7090 if (klass->image->uncompressed_metadata)
7091 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
7092 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
7095 klass = klass->parent;
7098 g_assert_not_reached ();
7103 mono_field_get_index (MonoClassField *field)
7105 int index = field - field->parent->fields;
7107 g_assert (index >= 0 && index < field->parent->field.count);
7113 * mono_class_get_field_default_value:
7115 * Return the default value of the field as a pointer into the metadata blob.
7118 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
7121 guint32 constant_cols [MONO_CONSTANT_SIZE];
7123 MonoClass *klass = field->parent;
7125 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7127 if (!klass->ext || !klass->ext->field_def_values) {
7128 MonoFieldDefaultValue *def_values;
7130 mono_class_alloc_ext (klass);
7132 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
7134 mono_image_lock (klass->image);
7135 mono_memory_barrier ();
7136 if (!klass->ext->field_def_values)
7137 klass->ext->field_def_values = def_values;
7138 mono_image_unlock (klass->image);
7141 field_index = mono_field_get_index (field);
7143 if (!klass->ext->field_def_values [field_index].data) {
7144 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7148 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7150 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7151 klass->ext->field_def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7152 klass->ext->field_def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7155 *def_type = klass->ext->field_def_values [field_index].def_type;
7156 return klass->ext->field_def_values [field_index].data;
7160 mono_property_get_index (MonoProperty *prop)
7162 int index = prop - prop->parent->ext->properties;
7164 g_assert (index >= 0 && index < prop->parent->ext->property.count);
7170 * mono_class_get_property_default_value:
7172 * Return the default value of the field as a pointer into the metadata blob.
7175 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7178 guint32 constant_cols [MONO_CONSTANT_SIZE];
7179 MonoClass *klass = property->parent;
7181 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7183 * We don't cache here because it is not used by C# so it's quite rare, but
7184 * we still do the lookup in klass->ext because that is where the data
7185 * is stored for dynamic assemblies.
7188 if (image_is_dynamic (klass->image)) {
7189 int prop_index = mono_property_get_index (property);
7190 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
7191 *def_type = klass->ext->prop_def_values [prop_index].def_type;
7192 return klass->ext->prop_def_values [prop_index].data;
7196 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7200 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7201 *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7202 return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7206 mono_class_get_event_token (MonoEvent *event)
7208 MonoClass *klass = event->parent;
7213 for (i = 0; i < klass->ext->event.count; ++i) {
7214 if (&klass->ext->events [i] == event)
7215 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
7218 klass = klass->parent;
7221 g_assert_not_reached ();
7226 * mono_class_get_property_from_name:
7228 * @name: name of the property to lookup in the specified class
7230 * Use this method to lookup a property in a class
7231 * Returns: the MonoProperty with the given name, or NULL if the property
7232 * does not exist on the @klass.
7235 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7239 gpointer iter = NULL;
7240 while ((p = mono_class_get_properties (klass, &iter))) {
7241 if (! strcmp (name, p->name))
7244 klass = klass->parent;
7250 * mono_class_get_property_token:
7251 * @prop: MonoProperty to query
7253 * Returns: The ECMA token for the specified property.
7256 mono_class_get_property_token (MonoProperty *prop)
7258 MonoClass *klass = prop->parent;
7262 gpointer iter = NULL;
7263 while ((p = mono_class_get_properties (klass, &iter))) {
7264 if (&klass->ext->properties [i] == prop)
7265 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
7269 klass = klass->parent;
7272 g_assert_not_reached ();
7277 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7279 const char *name, *nspace;
7280 if (image_is_dynamic (image))
7281 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7283 switch (type_token & 0xff000000){
7284 case MONO_TOKEN_TYPE_DEF: {
7285 guint32 cols [MONO_TYPEDEF_SIZE];
7286 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7287 guint tidx = mono_metadata_token_index (type_token);
7289 if (tidx > tt->rows)
7290 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7292 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7293 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7294 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7295 if (strlen (nspace) == 0)
7296 return g_strdup_printf ("%s", name);
7298 return g_strdup_printf ("%s.%s", nspace, name);
7301 case MONO_TOKEN_TYPE_REF: {
7303 guint32 cols [MONO_TYPEREF_SIZE];
7304 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7305 guint tidx = mono_metadata_token_index (type_token);
7308 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7310 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7311 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7312 mono_error_cleanup (&error);
7316 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7317 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7318 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7319 if (strlen (nspace) == 0)
7320 return g_strdup_printf ("%s", name);
7322 return g_strdup_printf ("%s.%s", nspace, name);
7325 case MONO_TOKEN_TYPE_SPEC:
7326 return g_strdup_printf ("Typespec 0x%08x", type_token);
7328 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7333 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7335 if (image_is_dynamic (image))
7336 return g_strdup_printf ("DynamicAssembly %s", image->name);
7338 switch (type_token & 0xff000000){
7339 case MONO_TOKEN_TYPE_DEF:
7340 if (image->assembly)
7341 return mono_stringify_assembly_name (&image->assembly->aname);
7342 else if (image->assembly_name)
7343 return g_strdup (image->assembly_name);
7344 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7345 case MONO_TOKEN_TYPE_REF: {
7347 MonoAssemblyName aname;
7348 guint32 cols [MONO_TYPEREF_SIZE];
7349 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7350 guint32 idx = mono_metadata_token_index (type_token);
7353 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7355 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7356 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7357 mono_error_cleanup (&error);
7360 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7362 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7363 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7364 case MONO_RESOLUTION_SCOPE_MODULE:
7366 return g_strdup ("");
7367 case MONO_RESOLUTION_SCOPE_MODULEREF:
7369 return g_strdup ("");
7370 case MONO_RESOLUTION_SCOPE_TYPEREF:
7372 return g_strdup ("");
7373 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7374 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7375 return mono_stringify_assembly_name (&aname);
7377 g_assert_not_reached ();
7381 case MONO_TOKEN_TYPE_SPEC:
7383 return g_strdup ("");
7385 g_assert_not_reached ();
7392 * mono_class_get_full:
7393 * @image: the image where the class resides
7394 * @type_token: the token for the class
7395 * @context: the generic context used to evaluate generic instantiations in
7396 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7398 * Returns: The MonoClass that represents @type_token in @image
7401 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7405 klass = mono_class_get_checked (image, type_token, &error);
7407 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7408 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7410 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7416 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7420 mono_error_init (error);
7421 klass = mono_class_get_checked (image, type_token, error);
7423 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7424 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7429 * mono_class_get_checked:
7430 * @image: the image where the class resides
7431 * @type_token: the token for the class
7432 * @error: error object to return any error
7434 * Returns: The MonoClass that represents @type_token in @image, or NULL on error.
7437 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7439 MonoClass *klass = NULL;
7441 mono_error_init (error);
7443 if (image_is_dynamic (image)) {
7444 int table = mono_metadata_token_table (type_token);
7446 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7447 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7450 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
7454 switch (type_token & 0xff000000){
7455 case MONO_TOKEN_TYPE_DEF:
7456 klass = mono_class_create_from_typedef (image, type_token, error);
7458 case MONO_TOKEN_TYPE_REF:
7459 klass = mono_class_from_typeref_checked (image, type_token, error);
7461 case MONO_TOKEN_TYPE_SPEC:
7462 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7465 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7469 /* Generic case, should be avoided for when a better error is possible. */
7470 if (!klass && mono_error_ok (error)) {
7471 char *name = mono_class_name_from_token (image, type_token);
7472 char *assembly = mono_assembly_name_from_token (image, type_token);
7473 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7481 * mono_type_get_checked:
7482 * @image: the image where the type resides
7483 * @type_token: the token for the type
7484 * @context: the generic context used to evaluate generic instantiations in
7485 * @error: Error handling context
7487 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7489 * Returns: The MonoType that represents @type_token in @image
7492 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7494 MonoType *type = NULL;
7495 gboolean inflated = FALSE;
7497 mono_error_init (error);
7499 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7500 if (image_is_dynamic (image)) {
7501 MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
7502 return_val_if_nok (error, NULL);
7503 return mono_class_get_type (klass);
7506 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7507 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7514 return mono_class_get_type (klass);
7517 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7524 MonoType *tmp = type;
7525 type = mono_class_get_type (mono_class_from_mono_type (type));
7526 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7527 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7528 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7530 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7532 if (type->type != tmp->type)
7535 mono_metadata_free_type (tmp);
7542 * @image: image where the class token will be looked up.
7543 * @type_token: a type token from the image
7545 * Returns the MonoClass with the given @type_token on the @image
7548 mono_class_get (MonoImage *image, guint32 type_token)
7550 return mono_class_get_full (image, type_token, NULL);
7554 * mono_image_init_name_cache:
7556 * Initializes the class name cache stored in image->name_cache.
7558 * LOCKING: Acquires the corresponding image lock.
7561 mono_image_init_name_cache (MonoImage *image)
7563 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7564 guint32 cols [MONO_TYPEDEF_SIZE];
7567 guint32 i, visib, nspace_index;
7568 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7570 if (image->name_cache)
7573 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7575 if (image_is_dynamic (image)) {
7576 mono_image_lock (image);
7577 if (image->name_cache) {
7578 /* Somebody initialized it before us */
7579 g_hash_table_destroy (the_name_cache);
7581 mono_atomic_store_release (&image->name_cache, the_name_cache);
7583 mono_image_unlock (image);
7587 /* Temporary hash table to avoid lookups in the nspace_table */
7588 name_cache2 = g_hash_table_new (NULL, NULL);
7590 for (i = 1; i <= t->rows; ++i) {
7591 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7592 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7594 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7595 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7597 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7599 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7600 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7602 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7603 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7604 if (!nspace_table) {
7605 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7606 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7607 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7610 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7613 /* Load type names from EXPORTEDTYPES table */
7615 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7616 guint32 cols [MONO_EXP_TYPE_SIZE];
7619 for (i = 0; i < t->rows; ++i) {
7620 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7622 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7623 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7627 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7628 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7630 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7631 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7632 if (!nspace_table) {
7633 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7634 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7635 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7638 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7642 g_hash_table_destroy (name_cache2);
7644 mono_image_lock (image);
7645 if (image->name_cache) {
7646 /* Somebody initialized it before us */
7647 g_hash_table_destroy (the_name_cache);
7649 mono_atomic_store_release (&image->name_cache, the_name_cache);
7651 mono_image_unlock (image);
7654 /*FIXME Only dynamic assemblies should allow this operation.*/
7656 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7657 const char *name, guint32 index)
7659 GHashTable *nspace_table;
7660 GHashTable *name_cache;
7663 mono_image_init_name_cache (image);
7664 mono_image_lock (image);
7666 name_cache = image->name_cache;
7667 if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7668 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7669 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7672 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7673 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7675 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7677 mono_image_unlock (image);
7686 find_nocase (gpointer key, gpointer value, gpointer user_data)
7688 char *name = (char*)key;
7689 FindUserData *data = (FindUserData*)user_data;
7691 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7692 data->value = value;
7696 * mono_class_from_name_case:
7697 * @image: The MonoImage where the type is looked up in
7698 * @name_space: the type namespace
7699 * @name: the type short name.
7700 * @deprecated: use the mono_class_from_name_case_checked variant instead.
7702 * Obtains a MonoClass with a given namespace and a given name which
7703 * is located in the given MonoImage. The namespace and name
7704 * lookups are case insensitive.
7707 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7710 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7711 mono_error_cleanup (&error);
7717 * mono_class_from_name_case:
7718 * @image: The MonoImage where the type is looked up in
7719 * @name_space: the type namespace
7720 * @name: the type short name.
7723 * Obtains a MonoClass with a given namespace and a given name which
7724 * is located in the given MonoImage. The namespace and name
7725 * lookups are case insensitive.
7727 * Returns: The MonoClass if the given namespace and name were found, or NULL if it
7728 * was not found. The @error object will contain information about the problem
7732 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7734 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7735 guint32 cols [MONO_TYPEDEF_SIZE];
7740 mono_error_init (error);
7742 if (image_is_dynamic (image)) {
7744 FindUserData user_data;
7746 mono_image_init_name_cache (image);
7747 mono_image_lock (image);
7749 user_data.key = name_space;
7750 user_data.value = NULL;
7751 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7753 if (user_data.value) {
7754 GHashTable *nspace_table = (GHashTable*)user_data.value;
7756 user_data.key = name;
7757 user_data.value = NULL;
7759 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7761 if (user_data.value)
7762 token = GPOINTER_TO_UINT (user_data.value);
7765 mono_image_unlock (image);
7768 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7774 /* add a cache if needed */
7775 for (i = 1; i <= t->rows; ++i) {
7776 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7777 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7779 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7780 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7782 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7784 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7785 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7786 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7787 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7793 return_nested_in (MonoClass *klass, char *nested)
7796 char *s = strchr (nested, '/');
7797 gpointer iter = NULL;
7804 while ((found = mono_class_get_nested_types (klass, &iter))) {
7805 if (strcmp (found->name, nested) == 0) {
7807 return return_nested_in (found, s);
7815 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7817 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7818 MonoImage *file_image;
7822 mono_error_init (error);
7825 * The EXPORTEDTYPES table only contains public types, so have to search the
7827 * Note: image->modules contains the contents of the MODULEREF table, while
7828 * the real module list is in the FILE table.
7830 for (i = 0; i < file_table->rows; i++) {
7831 guint32 cols [MONO_FILE_SIZE];
7832 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7833 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7836 file_image = mono_image_load_file_for_image_checked (image, i + 1, error);
7838 klass = mono_class_from_name_checked (file_image, name_space, name, error);
7839 if (klass || !is_ok (error))
7848 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7850 GHashTable *nspace_table;
7851 MonoImage *loaded_image;
7858 mono_error_init (error);
7860 // Checking visited images avoids stack overflows when cyclic references exist.
7861 if (g_hash_table_lookup (visited_images, image))
7864 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7866 if ((nested = strchr (name, '/'))) {
7867 int pos = nested - name;
7868 int len = strlen (name);
7871 memcpy (buf, name, len + 1);
7873 nested = buf + pos + 1;
7877 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7878 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7879 gboolean res = get_class_from_name (image, name_space, name, &klass);
7882 klass = search_modules (image, name_space, name, error);
7887 return klass ? return_nested_in (klass, nested) : NULL;
7893 mono_image_init_name_cache (image);
7894 mono_image_lock (image);
7896 nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7899 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7901 mono_image_unlock (image);
7903 if (!token && image_is_dynamic (image) && image->modules) {
7904 /* Search modules as well */
7905 for (i = 0; i < image->module_count; ++i) {
7906 MonoImage *module = image->modules [i];
7908 klass = mono_class_from_name_checked (module, name_space, name, error);
7909 if (klass || !is_ok (error))
7915 klass = search_modules (image, name_space, name, error);
7916 if (klass || !is_ok (error))
7921 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7922 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7923 guint32 cols [MONO_EXP_TYPE_SIZE];
7926 idx = mono_metadata_token_index (token);
7928 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7930 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7931 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7932 loaded_image = mono_assembly_load_module_checked (image->assembly, impl >> MONO_IMPLEMENTATION_BITS, error);
7935 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7937 return klass ? return_nested_in (klass, nested) : NULL;
7939 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7940 guint32 assembly_idx;
7942 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7944 mono_assembly_load_reference (image, assembly_idx - 1);
7945 g_assert (image->references [assembly_idx - 1]);
7946 if (image->references [assembly_idx - 1] == (gpointer)-1)
7948 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
7950 return klass ? return_nested_in (klass, nested) : NULL;
7953 g_assert_not_reached ();
7957 token = MONO_TOKEN_TYPE_DEF | token;
7959 klass = mono_class_get_checked (image, token, error);
7961 return return_nested_in (klass, nested);
7966 * mono_class_from_name_checked:
7967 * @image: The MonoImage where the type is looked up in
7968 * @name_space: the type namespace
7969 * @name: the type short name.
7971 * Obtains a MonoClass with a given namespace and a given name which
7972 * is located in the given MonoImage.
7974 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
7975 * set if the class was not found or it will return NULL and set the error if there was a loading error.
7978 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7981 GHashTable *visited_images;
7983 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7985 klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
7987 g_hash_table_destroy (visited_images);
7993 * mono_class_from_name:
7994 * @image: The MonoImage where the type is looked up in
7995 * @name_space: the type namespace
7996 * @name: the type short name.
7998 * Obtains a MonoClass with a given namespace and a given name which
7999 * is located in the given MonoImage.
8001 * To reference nested classes, use the "/" character as a separator.
8002 * For example use "Foo/Bar" to reference the class Bar that is nested
8003 * inside Foo, like this: "class Foo { class Bar {} }".
8006 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
8011 klass = mono_class_from_name_checked (image, name_space, name, &error);
8012 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
8018 * mono_class_load_from_name:
8019 * @image: The MonoImage where the type is looked up in
8020 * @name_space: the type namespace
8021 * @name: the type short name.
8023 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
8024 * This function should be used by the runtime for critical types to which there's no way to recover but crash
8025 * If they are missing. Thing of System.Object or System.String.
8028 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
8033 klass = mono_class_from_name_checked (image, name_space, name, &error);
8035 g_error ("Runtime critical type %s.%s not found", name_space, name);
8036 if (!mono_error_ok (&error))
8037 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8042 * mono_class_try_load_from_name:
8043 * @image: The MonoImage where the type is looked up in
8044 * @name_space: the type namespace
8045 * @name: the type short name.
8047 * This function tries to load a type, returning the class was found or NULL otherwise.
8048 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
8050 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
8051 * a type that we would otherwise assume to be available but was not due some error.
8055 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
8060 klass = mono_class_from_name_checked (image, name_space, name, &error);
8061 if (!mono_error_ok (&error))
8062 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8068 * mono_class_is_subclass_of:
8069 * @klass: class to probe if it is a subclass of another one
8070 * @klassc: the class we suspect is the base class
8071 * @check_interfaces: whether we should perform interface checks
8073 * This method determines whether @klass is a subclass of @klassc.
8075 * If the @check_interfaces flag is set, then if @klassc is an interface
8076 * this method return TRUE if the @klass implements the interface or
8077 * if @klass is an interface, if one of its base classes is @klass.
8079 * If @check_interfaces is false then, then if @klass is not an interface
8080 * then it returns TRUE if the @klass is a subclass of @klassc.
8082 * if @klass is an interface and @klassc is System.Object, then this function
8087 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
8088 gboolean check_interfaces)
8090 /* FIXME test for interfaces with variant generic arguments */
8091 mono_class_init (klass);
8092 mono_class_init (klassc);
8094 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
8095 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
8097 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
8100 for (i = 0; i < klass->interface_count; i ++) {
8101 MonoClass *ic = klass->interfaces [i];
8106 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
8111 * MS.NET thinks interfaces are a subclass of Object, so we think it as
8114 if (klassc == mono_defaults.object_class)
8121 mono_type_is_generic_argument (MonoType *type)
8123 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
8127 mono_class_has_variant_generic_params (MonoClass *klass)
8130 MonoGenericContainer *container;
8132 if (!mono_class_is_ginst (klass))
8135 container = mono_class_get_generic_container (mono_class_get_generic_class (klass)->container_class);
8137 for (i = 0; i < container->type_argc; ++i)
8138 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8145 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8147 if (target == candidate)
8150 if (check_for_reference_conv &&
8151 mono_type_is_generic_argument (&target->byval_arg) &&
8152 mono_type_is_generic_argument (&candidate->byval_arg)) {
8153 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8154 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8156 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8159 if (!mono_class_is_assignable_from (target, candidate))
8165 * @container the generic container from the GTD
8166 * @klass: the class to be assigned to
8167 * @oklass: the source class
8169 * Both @klass and @oklass must be instances of the same generic interface.
8171 * Returns: TRUE if @klass can be assigned to a @klass variable
8174 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8177 MonoType **klass_argv, **oklass_argv;
8178 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8179 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8181 if (klass == oklass)
8184 /*Viable candidates are instances of the same generic interface*/
8185 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8188 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8189 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8191 for (j = 0; j < container->type_argc; ++j) {
8192 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8193 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8195 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8199 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8200 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8202 if (param1_class != param2_class) {
8203 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8204 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8206 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8207 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8217 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8219 MonoGenericParam *gparam, *ogparam;
8220 MonoGenericParamInfo *tinfo, *cinfo;
8221 MonoClass **candidate_class;
8222 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8225 if (target == candidate)
8227 if (target->byval_arg.type != candidate->byval_arg.type)
8230 gparam = target->byval_arg.data.generic_param;
8231 ogparam = candidate->byval_arg.data.generic_param;
8232 tinfo = mono_generic_param_info (gparam);
8233 cinfo = mono_generic_param_info (ogparam);
8235 class_constraint_satisfied = FALSE;
8236 valuetype_constraint_satisfied = FALSE;
8238 /*candidate must have a super set of target's special constraints*/
8239 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8240 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8242 if (cinfo->constraints) {
8243 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8244 MonoClass *cc = *candidate_class;
8246 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8247 class_constraint_satisfied = TRUE;
8248 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8249 valuetype_constraint_satisfied = TRUE;
8252 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8253 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8255 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8257 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8259 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8260 valuetype_constraint_satisfied)) {
8265 /*candidate type constraints must be a superset of target's*/
8266 if (tinfo->constraints) {
8267 MonoClass **target_class;
8268 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8269 MonoClass *tc = *target_class;
8272 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8273 * check it's constraints since it satisfy the constraint by itself.
8275 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8278 if (!cinfo->constraints)
8281 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8282 MonoClass *cc = *candidate_class;
8284 if (mono_class_is_assignable_from (tc, cc))
8288 * This happens when we have the following:
8290 * Bar<K> where K : IFace
8291 * Foo<T, U> where T : U where U : IFace
8293 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8296 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8297 if (mono_gparam_is_assignable_from (target, cc))
8301 if (!*candidate_class)
8306 /*candidate itself must have a constraint that satisfy target*/
8307 if (cinfo->constraints) {
8308 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8309 MonoClass *cc = *candidate_class;
8310 if (mono_class_is_assignable_from (target, cc))
8318 * mono_class_is_assignable_from:
8319 * @klass: the class to be assigned to
8320 * @oklass: the source class
8322 * Returns: TRUE if an instance of object oklass can be assigned to an
8323 * instance of object @klass
8326 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8329 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8331 mono_class_init (klass);
8333 if (!oklass->inited)
8334 mono_class_init (oklass);
8336 if (mono_class_has_failure (klass) || mono_class_has_failure (oklass))
8339 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8340 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8342 return mono_gparam_is_assignable_from (klass, oklass);
8345 if (MONO_CLASS_IS_INTERFACE (klass)) {
8346 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8347 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8348 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8352 for (i = 0; constraints [i]; ++i) {
8353 if (mono_class_is_assignable_from (klass, constraints [i]))
8361 /* interface_offsets might not be set for dynamic classes */
8362 if (oklass->ref_info_handle && !oklass->interface_bitmap) {
8364 * oklass might be a generic type parameter but they have
8365 * interface_offsets set.
8367 gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8368 if (!is_ok (&error)) {
8369 mono_error_cleanup (&error);
8374 if (!oklass->interface_bitmap)
8375 /* Happens with generic instances of not-yet created dynamic types */
8377 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8380 if (mono_class_has_variant_generic_params (klass)) {
8382 mono_class_setup_interfaces (oklass, &error);
8383 if (!mono_error_ok (&error)) {
8384 mono_error_cleanup (&error);
8388 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8389 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8390 MonoClass *iface = oklass->interfaces_packed [i];
8392 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8397 } else if (klass->delegate) {
8398 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8400 }else if (klass->rank) {
8401 MonoClass *eclass, *eoclass;
8403 if (oklass->rank != klass->rank)
8406 /* vectors vs. one dimensional arrays */
8407 if (oklass->byval_arg.type != klass->byval_arg.type)
8410 eclass = klass->cast_class;
8411 eoclass = oklass->cast_class;
8414 * a is b does not imply a[] is b[] when a is a valuetype, and
8415 * b is a reference type.
8418 if (eoclass->valuetype) {
8419 if ((eclass == mono_defaults.enum_class) ||
8420 (eclass == mono_defaults.enum_class->parent) ||
8421 (eclass == mono_defaults.object_class))
8425 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8426 } else if (mono_class_is_nullable (klass)) {
8427 if (mono_class_is_nullable (oklass))
8428 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8430 return mono_class_is_assignable_from (klass->cast_class, oklass);
8431 } else if (klass == mono_defaults.object_class)
8434 return mono_class_has_parent (oklass, klass);
8437 /*Check if @oklass is variant compatible with @klass.*/
8439 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8442 MonoType **klass_argv, **oklass_argv;
8443 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8444 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8446 /*Viable candidates are instances of the same generic interface*/
8447 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8450 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8451 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8453 for (j = 0; j < container->type_argc; ++j) {
8454 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8455 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8457 if (param1_class->valuetype != param2_class->valuetype)
8461 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8462 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8464 if (param1_class != param2_class) {
8465 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8466 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8468 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8469 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8477 /*Check if @candidate implements the interface @target*/
8479 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8483 gboolean is_variant = mono_class_has_variant_generic_params (target);
8485 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8486 if (mono_class_is_variant_compatible_slow (target, candidate))
8491 if (candidate == target)
8494 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8495 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8496 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (candidate);
8498 if (tb && tb->interfaces) {
8499 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8500 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8501 MonoClass *iface_class;
8503 /* we can't realize the type here since it can do pretty much anything. */
8506 iface_class = mono_class_from_mono_type (iface->type);
8507 if (iface_class == target)
8509 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8511 if (mono_class_implement_interface_slow (target, iface_class))
8516 /*setup_interfaces don't mono_class_init anything*/
8517 /*FIXME this doesn't handle primitive type arrays.
8518 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8519 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8521 mono_class_setup_interfaces (candidate, &error);
8522 if (!mono_error_ok (&error)) {
8523 mono_error_cleanup (&error);
8527 for (i = 0; i < candidate->interface_count; ++i) {
8528 if (candidate->interfaces [i] == target)
8531 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8534 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8538 candidate = candidate->parent;
8539 } while (candidate);
8545 * Check if @oklass can be assigned to @klass.
8546 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8549 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8551 if (candidate == target)
8553 if (target == mono_defaults.object_class)
8556 if (mono_class_has_parent (candidate, target))
8559 /*If target is not an interface there is no need to check them.*/
8560 if (MONO_CLASS_IS_INTERFACE (target))
8561 return mono_class_implement_interface_slow (target, candidate);
8563 if (target->delegate && mono_class_has_variant_generic_params (target))
8564 return mono_class_is_variant_compatible (target, candidate, FALSE);
8567 MonoClass *eclass, *eoclass;
8569 if (target->rank != candidate->rank)
8572 /* vectors vs. one dimensional arrays */
8573 if (target->byval_arg.type != candidate->byval_arg.type)
8576 eclass = target->cast_class;
8577 eoclass = candidate->cast_class;
8580 * a is b does not imply a[] is b[] when a is a valuetype, and
8581 * b is a reference type.
8584 if (eoclass->valuetype) {
8585 if ((eclass == mono_defaults.enum_class) ||
8586 (eclass == mono_defaults.enum_class->parent) ||
8587 (eclass == mono_defaults.object_class))
8591 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8593 /*FIXME properly handle nullables */
8594 /*FIXME properly handle (M)VAR */
8599 * mono_class_get_cctor:
8600 * @klass: A MonoClass pointer
8602 * Returns: The static constructor of @klass if it exists, NULL otherwise.
8605 mono_class_get_cctor (MonoClass *klass)
8607 MonoCachedClassInfo cached_info;
8609 if (image_is_dynamic (klass->image)) {
8611 * has_cctor is not set for these classes because mono_class_init () is
8614 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8617 if (!klass->has_cctor)
8620 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8622 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8623 if (!mono_error_ok (&error))
8624 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8628 if (mono_class_is_ginst (klass) && !klass->methods)
8629 return mono_class_get_inflated_method (klass, mono_class_get_cctor (mono_class_get_generic_class (klass)->container_class));
8631 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8635 * mono_class_get_finalizer:
8636 * @klass: The MonoClass pointer
8638 * Returns: The finalizer method of @klass if it exists, NULL otherwise.
8641 mono_class_get_finalizer (MonoClass *klass)
8643 MonoCachedClassInfo cached_info;
8646 mono_class_init (klass);
8647 if (!mono_class_has_finalizer (klass))
8650 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8652 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8653 if (!mono_error_ok (&error))
8654 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8657 mono_class_setup_vtable (klass);
8658 return klass->vtable [finalize_slot];
8663 * mono_class_needs_cctor_run:
8664 * @klass: the MonoClass pointer
8665 * @caller: a MonoMethod describing the caller
8667 * Determines whenever the class has a static constructor and whenever it
8668 * needs to be called when executing CALLER.
8671 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8675 method = mono_class_get_cctor (klass);
8677 return (method == caller) ? FALSE : TRUE;
8683 * mono_class_array_element_size:
8686 * Returns: The number of bytes an element of type @klass
8687 * uses when stored into an array.
8690 mono_class_array_element_size (MonoClass *klass)
8692 MonoType *type = &klass->byval_arg;
8695 switch (type->type) {
8698 case MONO_TYPE_BOOLEAN:
8702 case MONO_TYPE_CHAR:
8711 case MONO_TYPE_CLASS:
8712 case MONO_TYPE_STRING:
8713 case MONO_TYPE_OBJECT:
8714 case MONO_TYPE_SZARRAY:
8715 case MONO_TYPE_ARRAY:
8716 return sizeof (gpointer);
8721 case MONO_TYPE_VALUETYPE:
8722 if (type->data.klass->enumtype) {
8723 type = mono_class_enum_basetype (type->data.klass);
8724 klass = klass->element_class;
8727 return mono_class_instance_size (klass) - sizeof (MonoObject);
8728 case MONO_TYPE_GENERICINST:
8729 type = &type->data.generic_class->container_class->byval_arg;
8732 case MONO_TYPE_MVAR: {
8735 return mono_type_size (type, &align);
8737 case MONO_TYPE_VOID:
8741 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8747 * mono_array_element_size:
8748 * @ac: pointer to a #MonoArrayClass
8750 * Returns: The size of single array element.
8753 mono_array_element_size (MonoClass *ac)
8755 g_assert (ac->rank);
8756 return ac->sizes.element_size;
8760 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8761 MonoGenericContext *context)
8764 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8765 g_assert (mono_error_ok (&error));
8770 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8771 MonoGenericContext *context, MonoError *error)
8773 mono_error_init (error);
8775 if (image_is_dynamic (image)) {
8776 MonoClass *tmp_handle_class;
8777 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
8779 mono_error_assert_ok (error);
8780 g_assert (tmp_handle_class);
8782 *handle_class = tmp_handle_class;
8784 if (tmp_handle_class == mono_defaults.typehandle_class)
8785 return &((MonoClass*)obj)->byval_arg;
8790 switch (token & 0xff000000) {
8791 case MONO_TOKEN_TYPE_DEF:
8792 case MONO_TOKEN_TYPE_REF:
8793 case MONO_TOKEN_TYPE_SPEC: {
8796 *handle_class = mono_defaults.typehandle_class;
8797 type = mono_type_get_checked (image, token, context, error);
8801 mono_class_init (mono_class_from_mono_type (type));
8802 /* We return a MonoType* as handle */
8805 case MONO_TOKEN_FIELD_DEF: {
8807 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8809 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8813 *handle_class = mono_defaults.fieldhandle_class;
8814 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8818 mono_class_init (klass);
8819 return mono_class_get_field (klass, token);
8821 case MONO_TOKEN_METHOD_DEF:
8822 case MONO_TOKEN_METHOD_SPEC: {
8824 meth = mono_get_method_checked (image, token, NULL, context, error);
8826 *handle_class = mono_defaults.methodhandle_class;
8832 case MONO_TOKEN_MEMBER_REF: {
8833 guint32 cols [MONO_MEMBERREF_SIZE];
8835 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8836 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8837 mono_metadata_decode_blob_size (sig, &sig);
8838 if (*sig == 0x6) { /* it's a field */
8840 MonoClassField *field;
8841 field = mono_field_from_token_checked (image, token, &klass, context, error);
8843 *handle_class = mono_defaults.fieldhandle_class;
8847 meth = mono_get_method_checked (image, token, NULL, context, error);
8849 *handle_class = mono_defaults.methodhandle_class;
8854 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8860 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
8862 MonoClass *handle_class;
8863 mono_error_init (error);
8864 return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
8868 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
8870 return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
8873 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8876 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8878 get_cached_class_info = func;
8882 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8884 if (!get_cached_class_info)
8887 return get_cached_class_info (klass, res);
8891 mono_install_get_class_from_name (MonoGetClassFromName func)
8893 get_class_from_name = func;
8897 * mono_class_get_image:
8899 * Use this method to get the `MonoImage*` where this class came from.
8901 * Returns: The image where this class is defined.
8904 mono_class_get_image (MonoClass *klass)
8906 return klass->image;
8910 * mono_class_get_element_class:
8911 * @klass: the MonoClass to act on
8913 * Use this function to get the element class of an array.
8915 * Returns: The element class of an array.
8918 mono_class_get_element_class (MonoClass *klass)
8920 return klass->element_class;
8924 * mono_class_is_valuetype:
8925 * @klass: the MonoClass to act on
8927 * Use this method to determine if the provided `MonoClass*` represents a value type,
8928 * or a reference type.
8930 * Returns: TRUE if the MonoClass represents a ValueType, FALSE if it represents a reference type.
8933 mono_class_is_valuetype (MonoClass *klass)
8935 return klass->valuetype;
8939 * mono_class_is_enum:
8940 * @klass: the MonoClass to act on
8942 * Use this function to determine if the provided `MonoClass*` represents an enumeration.
8944 * Returns: TRUE if the MonoClass represents an enumeration.
8947 mono_class_is_enum (MonoClass *klass)
8949 return klass->enumtype;
8953 * mono_class_enum_basetype:
8954 * @klass: the MonoClass to act on
8956 * Use this function to get the underlying type for an enumeration value.
8958 * Returns: The underlying type representation for an enumeration.
8961 mono_class_enum_basetype (MonoClass *klass)
8963 if (klass->element_class == klass)
8964 /* SRE or broken types */
8967 return &klass->element_class->byval_arg;
8971 * mono_class_get_parent
8972 * @klass: the MonoClass to act on
8974 * Returns: The parent class for this class.
8977 mono_class_get_parent (MonoClass *klass)
8979 return klass->parent;
8983 * mono_class_get_nesting_type:
8984 * @klass: the MonoClass to act on
8986 * Use this function to obtain the class that the provided `MonoClass*` is nested on.
8988 * If the return is NULL, this indicates that this class is not nested.
8990 * Returns: The container type where this type is nested or NULL if this type is not a nested type.
8993 mono_class_get_nesting_type (MonoClass *klass)
8995 return klass->nested_in;
8999 * mono_class_get_rank:
9000 * @klass: the MonoClass to act on
9002 * Returns: The rank for the array (the number of dimensions).
9005 mono_class_get_rank (MonoClass *klass)
9011 * mono_class_get_name
9012 * @klass: the MonoClass to act on
9014 * Returns: The name of the class.
9017 mono_class_get_name (MonoClass *klass)
9023 * mono_class_get_namespace:
9024 * @klass: the MonoClass to act on
9026 * Returns: The namespace of the class.
9029 mono_class_get_namespace (MonoClass *klass)
9031 return klass->name_space;
9035 * mono_class_get_type:
9036 * @klass: the MonoClass to act on
9038 * This method returns the internal Type representation for the class.
9040 * Returns: The MonoType from the class.
9043 mono_class_get_type (MonoClass *klass)
9045 return &klass->byval_arg;
9049 * mono_class_get_type_token:
9050 * @klass: the MonoClass to act on
9052 * This method returns type token for the class.
9054 * Returns: The type token for the class.
9057 mono_class_get_type_token (MonoClass *klass)
9059 return klass->type_token;
9063 * mono_class_get_byref_type:
9064 * @klass: the MonoClass to act on
9069 mono_class_get_byref_type (MonoClass *klass)
9071 return &klass->this_arg;
9075 * mono_class_num_fields:
9076 * @klass: the MonoClass to act on
9078 * Returns: The number of static and instance fields in the class.
9081 mono_class_num_fields (MonoClass *klass)
9083 return klass->field.count;
9087 * mono_class_num_methods:
9088 * @klass: the MonoClass to act on
9090 * Returns: The number of methods in the class.
9093 mono_class_num_methods (MonoClass *klass)
9095 return klass->method.count;
9099 * mono_class_num_properties
9100 * @klass: the MonoClass to act on
9102 * Returns: The number of properties in the class.
9105 mono_class_num_properties (MonoClass *klass)
9107 mono_class_setup_properties (klass);
9109 return klass->ext->property.count;
9113 * mono_class_num_events:
9114 * @klass: the MonoClass to act on
9116 * Returns: The number of events in the class.
9119 mono_class_num_events (MonoClass *klass)
9121 mono_class_setup_events (klass);
9123 return klass->ext->event.count;
9127 * mono_class_get_fields:
9128 * @klass: the MonoClass to act on
9130 * This routine is an iterator routine for retrieving the fields in a class.
9132 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9133 * iterate over all of the elements. When no more values are
9134 * available, the return value is NULL.
9136 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
9139 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9141 MonoClassField* field;
9145 mono_class_setup_fields (klass);
9146 if (mono_class_has_failure (klass))
9148 /* start from the first */
9149 if (klass->field.count) {
9150 *iter = &klass->fields [0];
9151 return &klass->fields [0];
9157 field = (MonoClassField *)*iter;
9159 if (field < &klass->fields [klass->field.count]) {
9167 * mono_class_get_methods
9168 * @klass: the MonoClass to act on
9170 * This routine is an iterator routine for retrieving the fields in a class.
9172 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9173 * iterate over all of the elements. When no more values are
9174 * available, the return value is NULL.
9176 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
9179 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9181 MonoMethod** method;
9185 mono_class_setup_methods (klass);
9188 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9189 * FIXME we should better report this error to the caller
9191 if (!klass->methods)
9193 /* start from the first */
9194 if (klass->method.count) {
9195 *iter = &klass->methods [0];
9196 return klass->methods [0];
9202 method = (MonoMethod **)*iter;
9204 if (method < &klass->methods [klass->method.count]) {
9212 * mono_class_get_virtual_methods:
9214 * Iterate over the virtual methods of KLASS.
9216 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9219 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9221 MonoMethod** method;
9224 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9226 mono_class_setup_methods (klass);
9228 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9229 * FIXME we should better report this error to the caller
9231 if (!klass->methods)
9233 /* start from the first */
9234 method = &klass->methods [0];
9236 method = (MonoMethod **)*iter;
9239 while (method < &klass->methods [klass->method.count]) {
9240 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9244 if (method < &klass->methods [klass->method.count]) {
9251 /* Search directly in metadata to avoid calling setup_methods () */
9252 MonoMethod *res = NULL;
9258 start_index = GPOINTER_TO_UINT (*iter);
9261 int first_idx = mono_class_get_first_method_idx (klass);
9262 for (i = start_index; i < klass->method.count; ++i) {
9265 /* first_idx points into the methodptr table */
9266 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
9268 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9272 if (i < klass->method.count) {
9274 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9275 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9277 /* Add 1 here so the if (*iter) check fails */
9278 *iter = GUINT_TO_POINTER (i + 1);
9287 * mono_class_get_properties:
9288 * @klass: the MonoClass to act on
9290 * This routine is an iterator routine for retrieving the properties in a class.
9292 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9293 * iterate over all of the elements. When no more values are
9294 * available, the return value is NULL.
9296 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9299 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9301 MonoProperty* property;
9305 mono_class_setup_properties (klass);
9306 /* start from the first */
9307 if (klass->ext->property.count) {
9308 *iter = &klass->ext->properties [0];
9309 return (MonoProperty *)*iter;
9315 property = (MonoProperty *)*iter;
9317 if (property < &klass->ext->properties [klass->ext->property.count]) {
9319 return (MonoProperty *)*iter;
9325 * mono_class_get_events:
9326 * @klass: the MonoClass to act on
9328 * This routine is an iterator routine for retrieving the properties in a class.
9330 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9331 * iterate over all of the elements. When no more values are
9332 * available, the return value is NULL.
9334 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9337 mono_class_get_events (MonoClass* klass, gpointer *iter)
9343 mono_class_setup_events (klass);
9344 /* start from the first */
9345 if (klass->ext->event.count) {
9346 *iter = &klass->ext->events [0];
9347 return (MonoEvent *)*iter;
9353 event = (MonoEvent *)*iter;
9355 if (event < &klass->ext->events [klass->ext->event.count]) {
9357 return (MonoEvent *)*iter;
9363 * mono_class_get_interfaces
9364 * @klass: the MonoClass to act on
9366 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9368 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9369 * iterate over all of the elements. When no more values are
9370 * available, the return value is NULL.
9372 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9375 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9383 mono_class_init (klass);
9384 if (!klass->interfaces_inited) {
9385 mono_class_setup_interfaces (klass, &error);
9386 if (!mono_error_ok (&error)) {
9387 mono_error_cleanup (&error);
9391 /* start from the first */
9392 if (klass->interface_count) {
9393 *iter = &klass->interfaces [0];
9394 return klass->interfaces [0];
9400 iface = (MonoClass **)*iter;
9402 if (iface < &klass->interfaces [klass->interface_count]) {
9410 setup_nested_types (MonoClass *klass)
9413 GList *classes, *nested_classes, *l;
9416 if (klass->nested_classes_inited)
9419 if (!klass->type_token)
9420 klass->nested_classes_inited = TRUE;
9422 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9426 guint32 cols [MONO_NESTED_CLASS_SIZE];
9427 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9428 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9429 if (!mono_error_ok (&error)) {
9430 /*FIXME don't swallow the error message*/
9431 mono_error_cleanup (&error);
9433 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9437 classes = g_list_prepend (classes, nclass);
9439 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9442 mono_class_alloc_ext (klass);
9444 nested_classes = NULL;
9445 for (l = classes; l; l = l->next)
9446 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9447 g_list_free (classes);
9449 mono_image_lock (klass->image);
9451 mono_memory_barrier ();
9452 if (!klass->nested_classes_inited) {
9453 klass->ext->nested_classes = nested_classes;
9454 mono_memory_barrier ();
9455 klass->nested_classes_inited = TRUE;
9458 mono_image_unlock (klass->image);
9462 * mono_class_get_nested_types
9463 * @klass: the MonoClass to act on
9465 * This routine is an iterator routine for retrieving the nested types of a class.
9466 * This works only if @klass is non-generic, or a generic type definition.
9468 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9469 * iterate over all of the elements. When no more values are
9470 * available, the return value is NULL.
9472 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9475 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9481 if (!klass->nested_classes_inited)
9482 setup_nested_types (klass);
9485 /* start from the first */
9486 if (klass->ext && klass->ext->nested_classes) {
9487 *iter = klass->ext->nested_classes;
9488 return (MonoClass *)klass->ext->nested_classes->data;
9490 /* no nested types */
9494 item = (GList *)*iter;
9498 return (MonoClass *)item->data;
9505 * mono_class_is_delegate
9506 * @klass: the MonoClass to act on
9508 * Returns: TRUE if the MonoClass represents a System.Delegate.
9511 mono_class_is_delegate (MonoClass *klass)
9513 return klass->delegate;
9517 * mono_class_implements_interface
9518 * @klass: The MonoClass to act on
9519 * @interface: The interface to check if @klass implements.
9521 * Returns: TRUE if @klass implements @interface.
9524 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9526 return mono_class_is_assignable_from (iface, klass);
9530 * mono_field_get_name:
9531 * @field: the MonoClassField to act on
9533 * Returns: The name of the field.
9536 mono_field_get_name (MonoClassField *field)
9542 * mono_field_get_type:
9543 * @field: the MonoClassField to act on
9545 * Returns: MonoType of the field.
9548 mono_field_get_type (MonoClassField *field)
9551 MonoType *type = mono_field_get_type_checked (field, &error);
9552 if (!mono_error_ok (&error)) {
9553 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9554 mono_error_cleanup (&error);
9561 * mono_field_get_type_checked:
9562 * @field: the MonoClassField to act on
9563 * @error: used to return any erro found while retrieving @field type
9565 * Returns: MonoType of the field.
9568 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9570 mono_error_init (error);
9572 mono_field_resolve_type (field, error);
9577 * mono_field_get_parent:
9578 * @field: the MonoClassField to act on
9580 * Returns: MonoClass where the field was defined.
9583 mono_field_get_parent (MonoClassField *field)
9585 return field->parent;
9589 * mono_field_get_flags;
9590 * @field: the MonoClassField to act on
9592 * The metadata flags for a field are encoded using the
9593 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9595 * Returns: The flags for the field.
9598 mono_field_get_flags (MonoClassField *field)
9601 return mono_field_resolve_flags (field);
9602 return field->type->attrs;
9606 * mono_field_get_offset:
9607 * @field: the MonoClassField to act on
9609 * Returns: The field offset.
9612 mono_field_get_offset (MonoClassField *field)
9614 return field->offset;
9618 mono_field_get_rva (MonoClassField *field)
9622 MonoClass *klass = field->parent;
9623 MonoFieldDefaultValue *field_def_values;
9625 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9627 if (!klass->ext || !klass->ext->field_def_values) {
9628 mono_class_alloc_ext (klass);
9630 field_def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9632 mono_image_lock (klass->image);
9633 if (!klass->ext->field_def_values)
9634 klass->ext->field_def_values = field_def_values;
9635 mono_image_unlock (klass->image);
9638 field_index = mono_field_get_index (field);
9640 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9641 int first_field_idx = mono_class_get_first_field_idx (klass);
9642 mono_metadata_field_info (field->parent->image, first_field_idx + field_index, NULL, &rva, NULL);
9644 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9645 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9648 return klass->ext->field_def_values [field_index].data;
9652 * mono_field_get_data:
9653 * @field: the MonoClassField to act on
9655 * Returns: A pointer to the metadata constant value or to the field
9656 * data if it has an RVA flag.
9659 mono_field_get_data (MonoClassField *field)
9661 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9662 MonoTypeEnum def_type;
9664 return mono_class_get_field_default_value (field, &def_type);
9665 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9666 return mono_field_get_rva (field);
9673 * mono_property_get_name:
9674 * @prop: the MonoProperty to act on
9676 * Returns: The name of the property
9679 mono_property_get_name (MonoProperty *prop)
9685 * mono_property_get_set_method
9686 * @prop: the MonoProperty to act on.
9688 * Returns: The setter method of the property (A MonoMethod)
9691 mono_property_get_set_method (MonoProperty *prop)
9697 * mono_property_get_get_method
9698 * @prop: the MonoProperty to act on.
9700 * Returns: The setter method of the property (A MonoMethod)
9703 mono_property_get_get_method (MonoProperty *prop)
9709 * mono_property_get_parent:
9710 * @prop: the MonoProperty to act on.
9712 * Returns: The MonoClass where the property was defined.
9715 mono_property_get_parent (MonoProperty *prop)
9717 return prop->parent;
9721 * mono_property_get_flags:
9722 * @prop: the MonoProperty to act on.
9724 * The metadata flags for a property are encoded using the
9725 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9727 * Returns: The flags for the property.
9730 mono_property_get_flags (MonoProperty *prop)
9736 * mono_event_get_name:
9737 * @event: the MonoEvent to act on
9739 * Returns: The name of the event.
9742 mono_event_get_name (MonoEvent *event)
9748 * mono_event_get_add_method:
9749 * @event: The MonoEvent to act on.
9751 * Returns: The @add' method for the event (a MonoMethod).
9754 mono_event_get_add_method (MonoEvent *event)
9760 * mono_event_get_remove_method:
9761 * @event: The MonoEvent to act on.
9763 * Returns: The @remove method for the event (a MonoMethod).
9766 mono_event_get_remove_method (MonoEvent *event)
9768 return event->remove;
9772 * mono_event_get_raise_method:
9773 * @event: The MonoEvent to act on.
9775 * Returns: The @raise method for the event (a MonoMethod).
9778 mono_event_get_raise_method (MonoEvent *event)
9780 return event->raise;
9784 * mono_event_get_parent:
9785 * @event: the MonoEvent to act on.
9787 * Returns: The MonoClass where the event is defined.
9790 mono_event_get_parent (MonoEvent *event)
9792 return event->parent;
9796 * mono_event_get_flags
9797 * @event: the MonoEvent to act on.
9799 * The metadata flags for an event are encoded using the
9800 * EVENT_* constants. See the tabledefs.h file for details.
9802 * Returns: The flags for the event.
9805 mono_event_get_flags (MonoEvent *event)
9807 return event->attrs;
9811 * mono_class_get_method_from_name:
9812 * @klass: where to look for the method
9813 * @name: name of the method
9814 * @param_count: number of parameters. -1 for any number.
9816 * Obtains a MonoMethod with a given name and number of parameters.
9817 * It only works if there are no multiple signatures for any given method name.
9820 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9822 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9826 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9828 MonoMethod *res = NULL;
9831 /* Search directly in the metadata to avoid calling setup_methods () */
9832 int first_idx = mono_class_get_first_method_idx (klass);
9833 for (i = 0; i < klass->method.count; ++i) {
9835 guint32 cols [MONO_METHOD_SIZE];
9837 MonoMethodSignature *sig;
9839 /* first_idx points into the methodptr table */
9840 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, first_idx + i, cols, MONO_METHOD_SIZE);
9842 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9843 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9845 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9848 if (param_count == -1) {
9852 sig = mono_method_signature_checked (method, &error);
9854 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9857 if (sig->param_count == param_count) {
9868 * mono_class_get_method_from_name_flags:
9869 * @klass: where to look for the method
9870 * @name_space: name of the method
9871 * @param_count: number of parameters. -1 for any number.
9872 * @flags: flags which must be set in the method
9874 * Obtains a MonoMethod with a given name and number of parameters.
9875 * It only works if there are no multiple signatures for any given method name.
9878 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9880 MonoMethod *res = NULL;
9883 mono_class_init (klass);
9885 if (mono_class_is_ginst (klass) && !klass->methods) {
9886 res = mono_class_get_method_from_name_flags (mono_class_get_generic_class (klass)->container_class, name, param_count, flags);
9889 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9890 if (!mono_error_ok (&error))
9891 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9896 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9897 mono_class_setup_methods (klass);
9899 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9900 See mono/tests/array_load_exception.il
9901 FIXME we should better report this error to the caller
9903 if (!klass->methods)
9905 for (i = 0; i < klass->method.count; ++i) {
9906 MonoMethod *method = klass->methods [i];
9908 if (method->name[0] == name [0] &&
9909 !strcmp (name, method->name) &&
9910 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9911 ((method->flags & flags) == flags)) {
9918 res = find_method_in_metadata (klass, name, param_count, flags);
9925 * mono_class_set_failure:
9926 * @klass: class in which the failure was detected
9927 * @ex_type: the kind of exception/error to be thrown (later)
9928 * @ex_data: exception data (specific to each type of exception/error)
9930 * Keep a detected failure informations in the class for later processing.
9931 * Note that only the first failure is kept.
9933 * LOCKING: Acquires the loader lock.
9936 mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error)
9938 g_assert (boxed_error != NULL);
9940 if (mono_class_has_failure (klass))
9943 mono_loader_lock ();
9944 klass->has_failure = 1;
9945 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, boxed_error);
9946 mono_loader_unlock ();
9952 mono_class_has_failure (const MonoClass *klass)
9954 g_assert (klass != NULL);
9955 return klass->has_failure != 0;
9960 * mono_class_set_type_load_failure:
9961 * @klass: class in which the failure was detected
9962 * @fmt: Printf-style error message string.
9964 * Collect detected failure informaion in the class for later processing.
9965 * The error is stored as a MonoErrorBoxed as with mono_error_set_type_load_class ()
9966 * Note that only the first failure is kept.
9968 * Returns FALSE if a failure was already set on the class, or TRUE otherwise.
9970 * LOCKING: Acquires the loader lock.
9973 mono_class_set_type_load_failure (MonoClass *klass, const char * fmt, ...)
9975 MonoError prepare_error;
9978 if (mono_class_has_failure (klass))
9981 mono_error_init (&prepare_error);
9983 va_start (args, fmt);
9984 mono_error_vset_type_load_class (&prepare_error, klass, fmt, args);
9987 MonoErrorBoxed *box = mono_error_box (&prepare_error, klass->image);
9988 mono_error_cleanup (&prepare_error);
9989 return mono_class_set_failure (klass, box);
9993 * mono_class_get_exception_data:
9995 * Return the exception_data property of KLASS.
9997 * LOCKING: Acquires the loader lock.
10000 mono_class_get_exception_data (const MonoClass *klass)
10002 return mono_image_property_lookup (klass->image, (MonoClass*)klass, MONO_CLASS_PROP_EXCEPTION_DATA);
10006 * mono_classes_init:
10008 * Initialize the resources used by this module.
10011 mono_classes_init (void)
10013 mono_os_mutex_init (&classes_mutex);
10015 mono_native_tls_alloc (&setup_fields_tls_id, NULL);
10016 mono_native_tls_alloc (&init_pending_tls_id, NULL);
10018 mono_counters_register ("MonoClassDef count",
10019 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_def_count);
10020 mono_counters_register ("MonoClassGtd count",
10021 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gtd_count);
10022 mono_counters_register ("MonoClassGenericInst count",
10023 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ginst_count);
10024 mono_counters_register ("MonoClassGenericParam count",
10025 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gparam_count);
10026 mono_counters_register ("MonoClassArray count",
10027 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_array_count);
10028 mono_counters_register ("MonoClassPointer count",
10029 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_pointer_count);
10030 mono_counters_register ("Inflated methods size",
10031 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
10032 mono_counters_register ("Inflated classes size",
10033 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
10034 mono_counters_register ("MonoClass size",
10035 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
10036 mono_counters_register ("MonoClassExt size",
10037 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
10039 mono_counters_register ("MonoClassExt count",
10040 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_count);
10044 * mono_classes_cleanup:
10046 * Free the resources used by this module.
10049 mono_classes_cleanup (void)
10051 mono_native_tls_free (setup_fields_tls_id);
10052 mono_native_tls_free (init_pending_tls_id);
10054 if (global_interface_bitset)
10055 mono_bitset_free (global_interface_bitset);
10056 global_interface_bitset = NULL;
10057 mono_os_mutex_destroy (&classes_mutex);
10061 * mono_class_get_exception_for_failure:
10062 * @klass: class in which the failure was detected
10064 * Return a constructed MonoException than the caller can then throw
10065 * using mono_raise_exception - or NULL if no failure is present (or
10066 * doesn't result in an exception).
10069 mono_class_get_exception_for_failure (MonoClass *klass)
10071 if (!mono_class_has_failure (klass))
10073 MonoError unboxed_error;
10074 mono_error_init (&unboxed_error);
10075 mono_error_set_for_class_failure (&unboxed_error, klass);
10076 return mono_error_convert_to_exception (&unboxed_error);
10080 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
10082 outer_klass = mono_class_get_generic_type_definition (outer_klass);
10083 inner_klass = mono_class_get_generic_type_definition (inner_klass);
10085 if (outer_klass == inner_klass)
10087 inner_klass = inner_klass->nested_in;
10088 } while (inner_klass);
10093 mono_class_get_generic_type_definition (MonoClass *klass)
10095 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
10096 return gklass ? gklass->container_class : klass;
10100 * Check if @klass is a subtype of @parent ignoring generic instantiations.
10102 * Generic instantiations are ignored for all super types of @klass.
10104 * Visibility checks ignoring generic instantiations.
10107 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
10110 klass = mono_class_get_generic_type_definition (klass);
10111 parent = mono_class_get_generic_type_definition (parent);
10112 mono_class_setup_supertypes (klass);
10114 for (i = 0; i < klass->idepth; ++i) {
10115 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
10121 * Subtype can only access parent members with family protection if the site object
10122 * is subclass of Subtype. For example:
10123 * class A { protected int x; }
10125 * void valid_access () {
10129 * void invalid_access () {
10136 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
10138 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
10141 if (context_klass == NULL)
10143 /*if access_klass is not member_klass context_klass must be type compat*/
10144 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10150 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10153 if (accessing == accessed)
10155 if (!accessed || !accessing)
10158 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10159 * anywhere so untrusted friends are not safe to access platform's code internals */
10160 if (mono_security_core_clr_enabled ()) {
10161 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10165 mono_assembly_load_friends (accessed);
10166 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10167 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10168 /* Be conservative with checks */
10169 if (!friend_->name)
10171 if (strcmp (accessing->aname.name, friend_->name))
10173 if (friend_->public_key_token [0]) {
10174 if (!accessing->aname.public_key_token [0])
10176 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10185 * If klass is a generic type or if it is derived from a generic type, return the
10186 * MonoClass of the generic definition
10187 * Returns NULL if not found
10190 get_generic_definition_class (MonoClass *klass)
10193 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
10194 if (gklass && gklass->container_class)
10195 return gklass->container_class;
10196 klass = klass->parent;
10202 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10205 for (i = 0; i < ginst->type_argc; ++i) {
10206 MonoType *type = ginst->type_argv[i];
10207 switch (type->type) {
10208 case MONO_TYPE_SZARRAY:
10209 if (!can_access_type (access_klass, type->data.klass))
10212 case MONO_TYPE_ARRAY:
10213 if (!can_access_type (access_klass, type->data.array->eklass))
10216 case MONO_TYPE_PTR:
10217 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10220 case MONO_TYPE_CLASS:
10221 case MONO_TYPE_VALUETYPE:
10222 case MONO_TYPE_GENERICINST:
10223 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10233 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10237 if (access_klass == member_klass)
10240 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10243 if (access_klass->element_class && !access_klass->enumtype)
10244 access_klass = access_klass->element_class;
10246 if (member_klass->element_class && !member_klass->enumtype)
10247 member_klass = member_klass->element_class;
10249 access_level = mono_class_get_flags (member_klass) & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10251 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10254 if (mono_class_is_ginst (member_klass) && !can_access_instantiation (access_klass, mono_class_get_generic_class (member_klass)->context.class_inst))
10257 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10260 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10263 /*Non nested type with nested visibility. We just fail it.*/
10264 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10267 switch (access_level) {
10268 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10269 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10271 case TYPE_ATTRIBUTE_PUBLIC:
10274 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10277 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10278 return is_nesting_type (member_klass, access_klass);
10280 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10281 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10283 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10284 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10286 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10287 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10288 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10290 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10291 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10292 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10297 /* FIXME: check visibility of type, too */
10299 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10301 MonoClass *member_generic_def;
10302 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10305 MonoGenericClass *access_gklass = mono_class_try_get_generic_class (access_klass);
10306 if (((access_gklass && access_gklass->container_class) ||
10307 mono_class_is_gtd (access_klass)) &&
10308 (member_generic_def = get_generic_definition_class (member_klass))) {
10309 MonoClass *access_container;
10311 if (mono_class_is_gtd (access_klass))
10312 access_container = access_klass;
10314 access_container = access_gklass->container_class;
10316 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10320 /* Partition I 8.5.3.2 */
10321 /* the access level values are the same for fields and methods */
10322 switch (access_level) {
10323 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10324 /* same compilation unit */
10325 return access_klass->image == member_klass->image;
10326 case FIELD_ATTRIBUTE_PRIVATE:
10327 return access_klass == member_klass;
10328 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10329 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10330 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10333 case FIELD_ATTRIBUTE_ASSEMBLY:
10334 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10335 case FIELD_ATTRIBUTE_FAMILY:
10336 if (is_valid_family_access (access_klass, member_klass, context_klass))
10339 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10340 if (is_valid_family_access (access_klass, member_klass, context_klass))
10342 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10343 case FIELD_ATTRIBUTE_PUBLIC:
10350 * mono_method_can_access_field:
10351 * @method: Method that will attempt to access the field
10352 * @field: the field to access
10354 * Used to determine if a method is allowed to access the specified field.
10356 * Returns: TRUE if the given @method is allowed to access the @field while following
10357 * the accessibility rules of the CLI.
10360 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10362 /* FIXME: check all overlapping fields */
10363 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10365 MonoClass *nested = method->klass->nested_in;
10367 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10370 nested = nested->nested_in;
10377 * mono_method_can_access_method:
10378 * @method: Method that will attempt to access the other method
10379 * @called: the method that we want to probe for accessibility.
10381 * Used to determine if the @method is allowed to access the specified @called method.
10383 * Returns: TRUE if the given @method is allowed to invoke the @called while following
10384 * the accessibility rules of the CLI.
10387 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10389 method = mono_method_get_method_definition (method);
10390 called = mono_method_get_method_definition (called);
10391 return mono_method_can_access_method_full (method, called, NULL);
10395 * mono_method_can_access_method_full:
10396 * @method: The caller method
10397 * @called: The called method
10398 * @context_klass: The static type on stack of the owner @called object used
10400 * This function must be used with instance calls, as they have more strict family accessibility.
10401 * It can be used with static methods, but context_klass should be NULL.
10403 * Returns: TRUE if caller have proper visibility and acessibility to @called
10406 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10408 /* Wrappers are except from access checks */
10409 if (method->wrapper_type != MONO_WRAPPER_NONE || called->wrapper_type != MONO_WRAPPER_NONE)
10412 MonoClass *access_class = method->klass;
10413 MonoClass *member_class = called->klass;
10414 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10416 MonoClass *nested = access_class->nested_in;
10418 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10421 nested = nested->nested_in;
10428 can = can_access_type (access_class, member_class);
10430 MonoClass *nested = access_class->nested_in;
10432 can = can_access_type (nested, member_class);
10435 nested = nested->nested_in;
10442 if (called->is_inflated) {
10443 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10444 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10453 * mono_method_can_access_field_full:
10454 * @method: The caller method
10455 * @field: The accessed field
10456 * @context_klass: The static type on stack of the owner @field object used
10458 * This function must be used with instance fields, as they have more strict family accessibility.
10459 * It can be used with static fields, but context_klass should be NULL.
10461 * Returns: TRUE if caller have proper visibility and acessibility to @field
10464 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10466 MonoClass *access_class = method->klass;
10467 MonoClass *member_class = field->parent;
10468 /* FIXME: check all overlapping fields */
10469 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10471 MonoClass *nested = access_class->nested_in;
10473 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10476 nested = nested->nested_in;
10483 can = can_access_type (access_class, member_class);
10485 MonoClass *nested = access_class->nested_in;
10487 can = can_access_type (nested, member_class);
10490 nested = nested->nested_in;
10500 * mono_class_can_access_class:
10501 * @source_class: The source class
10502 * @target_class: The accessed class
10504 * This function returns is @target_class is visible to @source_class
10506 * Returns: TRUE if source have proper visibility and acessibility to target
10509 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10511 return can_access_type (source_class, target_class);
10515 * mono_type_is_valid_enum_basetype:
10516 * @type: The MonoType to check
10518 * Returns: TRUE if the type can be used as the basetype of an enum
10520 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10521 switch (type->type) {
10524 case MONO_TYPE_BOOLEAN:
10527 case MONO_TYPE_CHAR:
10541 * mono_class_is_valid_enum:
10542 * @klass: An enum class to be validated
10544 * This method verify the required properties an enum should have.
10546 * Returns: TRUE if the informed enum class is valid
10548 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10549 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10550 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10553 mono_class_is_valid_enum (MonoClass *klass)
10555 MonoClassField * field;
10556 gpointer iter = NULL;
10557 gboolean found_base_field = FALSE;
10559 g_assert (klass->enumtype);
10560 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10561 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10565 if (!mono_class_is_auto_layout (klass))
10568 while ((field = mono_class_get_fields (klass, &iter))) {
10569 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10570 if (found_base_field)
10572 found_base_field = TRUE;
10573 if (!mono_type_is_valid_enum_basetype (field->type))
10578 if (!found_base_field)
10581 if (klass->method.count > 0)
10588 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10590 return gklass->context.class_inst == mono_class_get_generic_container (gklass->container_class)->context.class_inst;
10594 * mono_class_setup_interface_id:
10596 * Initializes MonoClass::interface_id if required.
10598 * LOCKING: Acquires the loader lock.
10601 mono_class_setup_interface_id (MonoClass *klass)
10603 mono_loader_lock ();
10604 if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10605 klass->interface_id = mono_get_unique_iid (klass);
10606 mono_loader_unlock ();
10610 * mono_class_alloc_ext:
10612 * Allocate klass->ext if not already done.
10615 mono_class_alloc_ext (MonoClass *klass)
10622 ext = (MonoClassExt *)mono_class_alloc0 (klass, sizeof (MonoClassExt));
10623 mono_image_lock (klass->image);
10624 mono_memory_barrier ();
10627 class_ext_size += sizeof (MonoClassExt);
10629 mono_image_unlock (klass->image);
10633 * mono_class_setup_interfaces:
10635 * Initialize klass->interfaces/interfaces_count.
10636 * LOCKING: Acquires the loader lock.
10637 * This function can fail the type.
10640 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10642 int i, interface_count;
10643 MonoClass **interfaces;
10645 mono_error_init (error);
10647 if (klass->interfaces_inited)
10650 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10651 MonoType *args [1];
10653 /* generic IList, ICollection, IEnumerable */
10654 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10655 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10657 args [0] = &klass->element_class->byval_arg;
10658 interfaces [0] = mono_class_bind_generic_parameters (
10659 mono_defaults.generic_ilist_class, 1, args, FALSE);
10660 if (interface_count > 1)
10661 interfaces [1] = mono_class_bind_generic_parameters (
10662 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10663 } else if (mono_class_is_ginst (klass)) {
10664 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
10666 mono_class_setup_interfaces (gklass, error);
10667 if (!mono_error_ok (error)) {
10668 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10672 interface_count = gklass->interface_count;
10673 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10674 for (i = 0; i < interface_count; i++) {
10675 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (mono_class_get_generic_class (klass)), error);
10676 if (!mono_error_ok (error)) {
10677 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10682 interface_count = 0;
10686 mono_image_lock (klass->image);
10688 if (!klass->interfaces_inited) {
10689 klass->interface_count = interface_count;
10690 klass->interfaces = interfaces;
10692 mono_memory_barrier ();
10694 klass->interfaces_inited = TRUE;
10697 mono_image_unlock (klass->image);
10701 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10703 MonoClass *klass = field->parent;
10704 MonoImage *image = klass->image;
10705 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10706 int field_idx = field - klass->fields;
10708 mono_error_init (error);
10711 MonoClassField *gfield = >d->fields [field_idx];
10712 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10713 if (!mono_error_ok (error)) {
10714 char *full_name = mono_type_get_full_name (gtd);
10715 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));
10716 g_free (full_name);
10719 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10720 if (!mono_error_ok (error)) {
10721 char *full_name = mono_type_get_full_name (klass);
10722 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));
10723 g_free (full_name);
10727 guint32 cols [MONO_FIELD_SIZE];
10728 MonoGenericContainer *container = NULL;
10729 int idx = mono_class_get_first_field_idx (klass) + field_idx;
10731 /*FIXME, in theory we do not lazy load SRE fields*/
10732 g_assert (!image_is_dynamic (image));
10734 if (mono_class_is_gtd (klass)) {
10735 container = mono_class_get_generic_container (klass);
10737 container = mono_class_get_generic_container (gtd);
10738 g_assert (container);
10741 /* first_field_idx and idx points into the fieldptr table */
10742 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10744 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10745 char *full_name = mono_type_get_full_name (klass);
10746 mono_error_set_type_load_class (error, klass, "Could not verify field '%s:%s' signature", full_name, field->name);;
10747 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
10748 g_free (full_name);
10752 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10754 mono_metadata_decode_value (sig, &sig);
10755 /* FIELD signature == 0x06 */
10756 g_assert (*sig == 0x06);
10758 field->type = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10759 if (!field->type) {
10760 char *full_name = mono_type_get_full_name (klass);
10761 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));
10762 g_free (full_name);
10768 mono_field_resolve_flags (MonoClassField *field)
10770 MonoClass *klass = field->parent;
10771 MonoImage *image = klass->image;
10772 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10773 int field_idx = field - klass->fields;
10777 MonoClassField *gfield = >d->fields [field_idx];
10778 return mono_field_get_flags (gfield);
10780 int idx = mono_class_get_first_field_idx (klass) + field_idx;
10782 /*FIXME, in theory we do not lazy load SRE fields*/
10783 g_assert (!image_is_dynamic (image));
10785 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10790 * mono_class_get_fields_lazy:
10791 * @klass: the MonoClass to act on
10793 * This routine is an iterator routine for retrieving the fields in a class.
10794 * Only minimal information about fields are loaded. Accessors must be used
10795 * for all MonoClassField returned.
10797 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10798 * iterate over all of the elements. When no more values are
10799 * available, the return value is NULL.
10801 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10804 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10806 MonoClassField* field;
10810 mono_class_setup_basic_field_info (klass);
10811 if (!klass->fields)
10813 /* start from the first */
10814 if (klass->field.count) {
10815 *iter = &klass->fields [0];
10816 return (MonoClassField *)*iter;
10822 field = (MonoClassField *)*iter;
10824 if (field < &klass->fields [klass->field.count]) {
10826 return (MonoClassField *)*iter;
10832 mono_class_full_name (MonoClass *klass)
10834 return mono_type_full_name (&klass->byval_arg);
10837 /* Declare all shared lazy type lookup functions */
10838 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, System.Runtime.InteropServices, SafeHandle)