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, inflated_classes_size, inflated_methods_size;
58 guint32 classes_size, class_ext_size;
60 /* Low level lock which protects data structures in this module */
61 static mono_mutex_t classes_mutex;
63 /* Function supplied by the runtime to find classes by name using information from the AOT file */
64 static MonoGetClassFromName get_class_from_name = NULL;
66 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error);
67 static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
68 static gboolean can_access_type (MonoClass *access_klass, MonoClass *member_klass);
69 static MonoMethod* find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags);
70 static int generic_array_methods (MonoClass *klass);
71 static void setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos);
73 static MonoMethod* mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter);
74 static char* mono_assembly_name_from_token (MonoImage *image, guint32 type_token);
75 static void mono_field_resolve_type (MonoClassField *field, MonoError *error);
76 static guint32 mono_field_resolve_flags (MonoClassField *field);
77 static void mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup);
78 static void mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gklass);
80 static gboolean mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data);
84 We use gclass recording to allow recursive system f types to be referenced by a parent.
86 Given the following type hierarchy:
88 class TextBox : TextBoxBase<TextBox> {}
89 class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
90 class TextInput<T> : Input<T> where T: TextInput<T> {}
93 The runtime tries to load TextBoxBase<>.
94 To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
95 To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
96 To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
98 At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded
99 at this point, iow, both are registered in the type map and both and a NULL parent. This means
100 that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
102 To fix that what we do is to record all generic instantes created while resolving the parent of
103 any generic type definition and, after resolved, correct the parent field if needed.
106 static int record_gclass_instantiation;
107 static GSList *gclass_recorded_list;
108 typedef gboolean (*gclass_record_func) (MonoClass*, void*);
113 mono_locks_os_acquire (&classes_mutex, ClassesLock);
117 classes_unlock (void)
119 mono_locks_os_release (&classes_mutex, ClassesLock);
123 * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
126 enable_gclass_recording (void)
128 ++record_gclass_instantiation;
132 * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
135 disable_gclass_recording (gclass_record_func func, void *user_data)
137 GSList **head = &gclass_recorded_list;
139 g_assert (record_gclass_instantiation > 0);
140 --record_gclass_instantiation;
143 GSList *node = *head;
144 if (func ((MonoClass*)node->data, user_data)) {
146 g_slist_free_1 (node);
152 /* We automatically discard all recorded gclasses when disabled. */
153 if (!record_gclass_instantiation && gclass_recorded_list) {
154 g_slist_free (gclass_recorded_list);
155 gclass_recorded_list = NULL;
160 * mono_class_from_typeref:
161 * @image: a MonoImage
162 * @type_token: a TypeRef token
164 * Creates the MonoClass* structure representing the type defined by
165 * the typeref token valid inside @image.
166 * Returns: The MonoClass* representing the typeref token, NULL ifcould
170 mono_class_from_typeref (MonoImage *image, guint32 type_token)
173 MonoClass *klass = mono_class_from_typeref_checked (image, type_token, &error);
174 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
179 * mono_class_from_typeref_checked:
180 * @image: a MonoImage
181 * @type_token: a TypeRef token
182 * @error: error return code, if any.
184 * Creates the MonoClass* structure representing the type defined by
185 * the typeref token valid inside @image.
187 * Returns: The MonoClass* representing the typeref token, NULL if it could
188 * not be loaded with the @error value filled with the information about the
192 mono_class_from_typeref_checked (MonoImage *image, guint32 type_token, MonoError *error)
194 guint32 cols [MONO_TYPEREF_SIZE];
195 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
197 const char *name, *nspace;
198 MonoClass *res = NULL;
201 mono_error_init (error);
203 if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, error))
206 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
208 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
209 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
211 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
212 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
213 case MONO_RESOLUTION_SCOPE_MODULE:
215 LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
216 This is not the observed behavior of existing implementations.
217 The defacto behavior is that it's just a typedef in disguise.
219 /* a typedef in disguise */
220 res = mono_class_from_name_checked (image, nspace, name, error);
223 case MONO_RESOLUTION_SCOPE_MODULEREF:
224 module = mono_image_load_module_checked (image, idx, error);
226 res = mono_class_from_name_checked (module, nspace, name, error);
229 case MONO_RESOLUTION_SCOPE_TYPEREF: {
230 MonoClass *enclosing;
233 if (idx == mono_metadata_token_index (type_token)) {
234 mono_error_set_bad_image (error, image, "Image with self-referencing typeref token %08x.", type_token);
238 enclosing = mono_class_from_typeref_checked (image, MONO_TOKEN_TYPE_REF | idx, error);
239 return_val_if_nok (error, NULL);
241 if (enclosing->nested_classes_inited && enclosing->ext) {
242 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
243 for (tmp = enclosing->ext->nested_classes; tmp; tmp = tmp->next) {
244 res = (MonoClass *)tmp->data;
245 if (strcmp (res->name, name) == 0)
249 /* Don't call mono_class_init as we might've been called by it recursively */
250 int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
252 guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
253 guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
254 const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
256 if (strcmp (nname, name) == 0)
257 return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, error);
259 i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
262 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name);
265 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
269 if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) {
270 mono_error_set_bad_image (error, image, "Image with invalid assemblyref token %08x.", idx);
274 if (!image->references || !image->references [idx - 1])
275 mono_assembly_load_reference (image, idx - 1);
276 g_assert (image->references [idx - 1]);
278 /* If the assembly did not load, register this as a type load exception */
279 if (image->references [idx - 1] == REFERENCE_MISSING){
280 MonoAssemblyName aname;
283 mono_assembly_get_assemblyref (image, idx - 1, &aname);
284 human_name = mono_stringify_assembly_name (&aname);
285 mono_error_set_assembly_load_simple (error, human_name, image->assembly ? image->assembly->ref_only : FALSE);
289 res = mono_class_from_name_checked (image->references [idx - 1]->image, nspace, name, error);
292 /* Generic case, should be avoided for when a better error is possible. */
293 if (!res && mono_error_ok (error)) {
294 char *name = mono_class_name_from_token (image, type_token);
295 char *assembly = mono_assembly_name_from_token (image, type_token);
296 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
303 mono_image_memdup (MonoImage *image, void *data, guint size)
305 void *res = mono_image_alloc (image, size);
306 memcpy (res, data, size);
310 /* Copy everything mono_metadata_free_array free. */
312 mono_dup_array_type (MonoImage *image, MonoArrayType *a)
315 a = (MonoArrayType *)mono_image_memdup (image, a, sizeof (MonoArrayType));
317 a->sizes = (int *)mono_image_memdup (image, a->sizes, a->numsizes * sizeof (int));
319 a->lobounds = (int *)mono_image_memdup (image, a->lobounds, a->numlobounds * sizeof (int));
321 a = (MonoArrayType *)g_memdup (a, sizeof (MonoArrayType));
323 a->sizes = (int *)g_memdup (a->sizes, a->numsizes * sizeof (int));
325 a->lobounds = (int *)g_memdup (a->lobounds, a->numlobounds * sizeof (int));
330 /* Copy everything mono_metadata_free_method_signature free. */
332 mono_metadata_signature_deep_dup (MonoImage *image, MonoMethodSignature *sig)
336 sig = mono_metadata_signature_dup_full (image, sig);
338 sig->ret = mono_metadata_type_dup (image, sig->ret);
339 for (i = 0; i < sig->param_count; ++i)
340 sig->params [i] = mono_metadata_type_dup (image, sig->params [i]);
346 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
348 MonoAssembly *ta = klass->image->assembly;
351 name = mono_stringify_assembly_name (&ta->aname);
352 g_string_append_printf (str, ", %s", name);
357 mono_type_name_check_byref (MonoType *type, GString *str)
360 g_string_append_c (str, '&');
364 * mono_identifier_escape_type_name_chars:
365 * @str: a destination string
366 * @identifier: an IDENTIFIER in internal form
370 * The displayed form of the identifier is appended to str.
372 * The displayed form of an identifier has the characters ,+&*[]\
373 * that have special meaning in type names escaped with a preceeding
374 * backslash (\) character.
377 mono_identifier_escape_type_name_chars (GString* str, const char* identifier)
383 // reserve space for common case: there will be no escaped characters.
384 g_string_set_size(str, n + strlen(identifier));
385 g_string_set_size(str, n);
387 for (const char* s = identifier; *s != 0 ; s++) {
396 g_string_append_c (str, '\\');
397 g_string_append_c (str, *s);
400 g_string_append_c (str, *s);
408 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
409 MonoTypeNameFormat format)
413 switch (type->type) {
414 case MONO_TYPE_ARRAY: {
415 int i, rank = type->data.array->rank;
416 MonoTypeNameFormat nested_format;
418 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
419 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
421 mono_type_get_name_recurse (
422 &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
423 g_string_append_c (str, '[');
425 g_string_append_c (str, '*');
426 for (i = 1; i < rank; i++)
427 g_string_append_c (str, ',');
428 g_string_append_c (str, ']');
430 mono_type_name_check_byref (type, str);
432 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
433 _mono_type_get_assembly_name (type->data.array->eklass, str);
436 case MONO_TYPE_SZARRAY: {
437 MonoTypeNameFormat nested_format;
439 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
440 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
442 mono_type_get_name_recurse (
443 &type->data.klass->byval_arg, str, FALSE, nested_format);
444 g_string_append (str, "[]");
446 mono_type_name_check_byref (type, str);
448 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
449 _mono_type_get_assembly_name (type->data.klass, str);
452 case MONO_TYPE_PTR: {
453 MonoTypeNameFormat nested_format;
455 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
456 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
458 mono_type_get_name_recurse (
459 type->data.type, str, FALSE, nested_format);
460 g_string_append_c (str, '*');
462 mono_type_name_check_byref (type, str);
464 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
465 _mono_type_get_assembly_name (mono_class_from_mono_type (type->data.type), str);
470 if (!mono_generic_param_info (type->data.generic_param))
471 g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num);
473 g_string_append (str, mono_generic_param_info (type->data.generic_param)->name);
475 mono_type_name_check_byref (type, str);
479 klass = mono_class_from_mono_type (type);
480 if (klass->nested_in) {
481 mono_type_get_name_recurse (
482 &klass->nested_in->byval_arg, str, TRUE, format);
483 if (format == MONO_TYPE_NAME_FORMAT_IL)
484 g_string_append_c (str, '.');
486 g_string_append_c (str, '+');
487 } else if (*klass->name_space) {
488 if (format == MONO_TYPE_NAME_FORMAT_IL)
489 g_string_append (str, klass->name_space);
491 mono_identifier_escape_type_name_chars (str, klass->name_space);
492 g_string_append_c (str, '.');
494 if (format == MONO_TYPE_NAME_FORMAT_IL) {
495 char *s = strchr (klass->name, '`');
496 int len = s ? s - klass->name : strlen (klass->name);
497 g_string_append_len (str, klass->name, len);
499 mono_identifier_escape_type_name_chars (str, klass->name);
503 if (klass->generic_class) {
504 MonoGenericClass *gclass = klass->generic_class;
505 MonoGenericInst *inst = gclass->context.class_inst;
506 MonoTypeNameFormat nested_format;
509 nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
510 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
512 if (format == MONO_TYPE_NAME_FORMAT_IL)
513 g_string_append_c (str, '<');
515 g_string_append_c (str, '[');
516 for (i = 0; i < inst->type_argc; i++) {
517 MonoType *t = inst->type_argv [i];
520 g_string_append_c (str, ',');
521 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
522 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
523 g_string_append_c (str, '[');
524 mono_type_get_name_recurse (inst->type_argv [i], str, FALSE, nested_format);
525 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
526 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
527 g_string_append_c (str, ']');
529 if (format == MONO_TYPE_NAME_FORMAT_IL)
530 g_string_append_c (str, '>');
532 g_string_append_c (str, ']');
533 } else if (klass->generic_container &&
534 (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
535 (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
538 if (format == MONO_TYPE_NAME_FORMAT_IL)
539 g_string_append_c (str, '<');
541 g_string_append_c (str, '[');
542 for (i = 0; i < klass->generic_container->type_argc; i++) {
544 g_string_append_c (str, ',');
545 g_string_append (str, mono_generic_container_get_param_info (klass->generic_container, i)->name);
547 if (format == MONO_TYPE_NAME_FORMAT_IL)
548 g_string_append_c (str, '>');
550 g_string_append_c (str, ']');
553 mono_type_name_check_byref (type, str);
555 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
556 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
557 _mono_type_get_assembly_name (klass, str);
563 * mono_type_get_name_full:
565 * @format: the format for the return string.
568 * Returns: The string representation in a number of formats:
570 * if format is MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
571 * returned in the formatrequired by System.Reflection, this is the
572 * inverse of mono_reflection_parse_type ().
574 * if format is MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
575 * be used by the IL assembler.
577 * if format is MONO_TYPE_NAME_FORMAT_FULL_NAME
579 * if format is MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
582 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
586 result = g_string_new ("");
588 mono_type_get_name_recurse (type, result, FALSE, format);
590 return g_string_free (result, FALSE);
594 * mono_type_get_full_name:
597 * Returns: The string representation for type as required by System.Reflection.
598 * The inverse of mono_reflection_parse_type ().
601 mono_type_get_full_name (MonoClass *klass)
603 return mono_type_get_name_full (mono_class_get_type (klass), MONO_TYPE_NAME_FORMAT_REFLECTION);
607 * mono_type_get_name:
610 * Returns: The string representation for type as it would be represented in IL code.
613 mono_type_get_name (MonoType *type)
615 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
619 * mono_type_get_underlying_type:
622 * Returns: The MonoType for the underlying integer type if @type
623 * is an enum and byref is false, otherwise the type itself.
626 mono_type_get_underlying_type (MonoType *type)
628 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype && !type->byref)
629 return mono_class_enum_basetype (type->data.klass);
630 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype && !type->byref)
631 return mono_class_enum_basetype (type->data.generic_class->container_class);
636 * mono_class_is_open_constructed_type:
639 * Returns: TRUE if type represents a generics open constructed type.
640 * IOW, not all type parameters required for the instantiation have
641 * been provided or it's a generic type definition.
643 * An open constructed type means it's a non realizable type. Not to
644 * be mixed up with an abstract type - we can't cast or dispatch to
645 * an open type, for example.
648 mono_class_is_open_constructed_type (MonoType *t)
654 case MONO_TYPE_SZARRAY:
655 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
656 case MONO_TYPE_ARRAY:
657 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
659 return mono_class_is_open_constructed_type (t->data.type);
660 case MONO_TYPE_GENERICINST:
661 return t->data.generic_class->context.class_inst->is_open;
662 case MONO_TYPE_CLASS:
663 case MONO_TYPE_VALUETYPE:
664 return t->data.klass->generic_container != NULL;
671 This is a simple function to catch the most common bad instances of generic types.
672 Specially those that might lead to further failures in the runtime.
675 is_valid_generic_argument (MonoType *type)
677 switch (type->type) {
679 //case MONO_TYPE_TYPEDBYREF:
687 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
689 mono_error_init (error);
691 switch (type->type) {
692 case MONO_TYPE_MVAR: {
694 int num = mono_type_get_generic_param_num (type);
695 MonoGenericInst *inst = context->method_inst;
698 if (num >= inst->type_argc) {
699 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
700 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
701 num, info ? info->name : "", inst->type_argc);
705 if (!is_valid_generic_argument (inst->type_argv [num])) {
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 with type 0x%x",
708 num, info ? info->name : "", inst->type_argv [num]->type);
712 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
713 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
714 * ->byref and ->attrs from @type are propagated to the returned type.
716 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
717 nt->byref = type->byref;
718 nt->attrs = type->attrs;
721 case MONO_TYPE_VAR: {
723 int num = mono_type_get_generic_param_num (type);
724 MonoGenericInst *inst = context->class_inst;
727 if (num >= inst->type_argc) {
728 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
729 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
730 num, info ? info->name : "", inst->type_argc);
733 if (!is_valid_generic_argument (inst->type_argv [num])) {
734 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
735 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
736 num, info ? info->name : "", inst->type_argv [num]->type);
739 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
740 nt->byref = type->byref;
741 nt->attrs = type->attrs;
744 case MONO_TYPE_SZARRAY: {
745 MonoClass *eclass = type->data.klass;
746 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
747 if (!inflated || !mono_error_ok (error))
749 nt = mono_metadata_type_dup (image, type);
750 nt->data.klass = mono_class_from_mono_type (inflated);
751 mono_metadata_free_type (inflated);
754 case MONO_TYPE_ARRAY: {
755 MonoClass *eclass = type->data.array->eklass;
756 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
757 if (!inflated || !mono_error_ok (error))
759 nt = mono_metadata_type_dup (image, type);
760 nt->data.array->eklass = mono_class_from_mono_type (inflated);
761 mono_metadata_free_type (inflated);
764 case MONO_TYPE_GENERICINST: {
765 MonoGenericClass *gclass = type->data.generic_class;
766 MonoGenericInst *inst;
768 if (!gclass->context.class_inst->is_open)
771 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
772 return_val_if_nok (error, NULL);
774 if (inst != gclass->context.class_inst)
775 gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
777 if (gclass == type->data.generic_class)
780 nt = mono_metadata_type_dup (image, type);
781 nt->data.generic_class = gclass;
784 case MONO_TYPE_CLASS:
785 case MONO_TYPE_VALUETYPE: {
786 MonoClass *klass = type->data.klass;
787 MonoGenericContainer *container = klass->generic_container;
788 MonoGenericInst *inst;
789 MonoGenericClass *gclass = NULL;
795 /* We can't use context->class_inst directly, since it can have more elements */
796 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
797 return_val_if_nok (error, NULL);
799 if (inst == container->context.class_inst)
802 gclass = mono_metadata_lookup_generic_class (klass, inst, image_is_dynamic (klass->image));
804 nt = mono_metadata_type_dup (image, type);
805 nt->type = MONO_TYPE_GENERICINST;
806 nt->data.generic_class = gclass;
816 mono_generic_class_get_context (MonoGenericClass *gclass)
818 return &gclass->context;
822 mono_class_get_context (MonoClass *klass)
824 return klass->generic_class ? mono_generic_class_get_context (klass->generic_class) : NULL;
828 * mono_class_get_generic_container:
830 * Return the generic container of KLASS which should be a generic type definition.
832 MonoGenericContainer*
833 mono_class_get_generic_container (MonoClass *klass)
835 g_assert (klass->is_generic);
837 return klass->generic_container;
841 * mono_class_get_generic_class:
843 * Return the MonoGenericClass of KLASS, which should be a generic instance.
846 mono_class_get_generic_class (MonoClass *klass)
848 g_assert (klass->is_inflated);
850 return klass->generic_class;
854 * mono_class_inflate_generic_type_with_mempool:
855 * @mempool: a mempool
857 * @context: a generics context
858 * @error: error context
860 * The same as mono_class_inflate_generic_type, but allocates the MonoType
861 * from mempool if it is non-NULL. If it is NULL, the MonoType is
862 * allocated on the heap and is owned by the caller.
863 * The returned type can potentially be the same as TYPE, so it should not be
864 * modified by the caller, and it should be freed using mono_metadata_free_type ().
867 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
869 MonoType *inflated = NULL;
870 mono_error_init (error);
873 inflated = inflate_generic_type (image, type, context, error);
874 return_val_if_nok (error, NULL);
877 MonoType *shared = mono_metadata_get_shared_type (type);
882 return mono_metadata_type_dup (image, type);
886 mono_stats.inflated_type_count++;
891 * mono_class_inflate_generic_type:
893 * @context: a generics context
895 * If @type is a generic type and @context is not NULL, instantiate it using the
896 * generics context @context.
898 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
899 * on the heap and is owned by the caller. Returns NULL on error.
901 * @deprecated Please use mono_class_inflate_generic_type_checked instead
904 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
908 result = mono_class_inflate_generic_type_checked (type, context, &error);
909 mono_error_cleanup (&error);
914 * mono_class_inflate_generic_type:
916 * @context: a generics context
917 * @error: error context to use
919 * If @type is a generic type and @context is not NULL, instantiate it using the
920 * generics context @context.
922 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
923 * on the heap and is owned by the caller.
926 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
928 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
932 * mono_class_inflate_generic_type_no_copy:
934 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
938 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
940 MonoType *inflated = NULL;
942 mono_error_init (error);
944 inflated = inflate_generic_type (image, type, context, error);
945 return_val_if_nok (error, NULL);
951 mono_stats.inflated_type_count++;
956 * mono_class_inflate_generic_class:
958 * Inflate the class @gklass with @context. Set @error on failure.
961 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
966 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
967 return_val_if_nok (error, NULL);
969 res = mono_class_from_mono_type (inflated);
970 mono_metadata_free_type (inflated);
975 static MonoGenericContext
976 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
978 MonoGenericInst *class_inst = NULL;
979 MonoGenericInst *method_inst = NULL;
980 MonoGenericContext res = { NULL, NULL };
982 mono_error_init (error);
984 if (context->class_inst) {
985 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
986 if (!mono_error_ok (error))
990 if (context->method_inst) {
991 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
992 if (!mono_error_ok (error))
996 res.class_inst = class_inst;
997 res.method_inst = method_inst;
1003 * mono_class_inflate_generic_method:
1004 * @method: a generic method
1005 * @context: a generics context
1007 * Instantiate the generic method @method using the generics context @context.
1009 * Returns: The new instantiated method
1012 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
1014 return mono_class_inflate_generic_method_full (method, NULL, context);
1018 mono_class_inflate_generic_method_checked (MonoMethod *method, MonoGenericContext *context, MonoError *error)
1020 return mono_class_inflate_generic_method_full_checked (method, NULL, context, error);
1024 * mono_class_inflate_generic_method_full:
1026 * Instantiate method @method with the generic context @context.
1027 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
1028 * Use mono_method_signature () and mono_method_get_header () to get the correct values.
1031 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
1034 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
1035 if (!mono_error_ok (&error))
1036 /*FIXME do proper error handling - on this case, kill this function. */
1037 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
1043 * mono_class_inflate_generic_method_full_checked:
1044 * Same as mono_class_inflate_generic_method_full but return failure using @error.
1047 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
1050 MonoMethodInflated *iresult, *cached;
1051 MonoMethodSignature *sig;
1052 MonoGenericContext tmp_context;
1054 mono_error_init (error);
1056 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1057 while (method->is_inflated) {
1058 MonoGenericContext *method_context = mono_method_get_context (method);
1059 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1061 tmp_context = inflate_generic_context (method_context, context, error);
1062 return_val_if_nok (error, NULL);
1064 context = &tmp_context;
1066 if (mono_metadata_generic_context_equal (method_context, context))
1069 method = imethod->declaring;
1073 * A method only needs to be inflated if the context has argument for which it is
1076 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1077 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1080 if (!((method->is_generic && context->method_inst) ||
1081 (method->klass->generic_container && context->class_inst)))
1084 iresult = g_new0 (MonoMethodInflated, 1);
1085 iresult->context = *context;
1086 iresult->declaring = method;
1088 if (!context->method_inst && method->is_generic)
1089 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1091 if (!context->class_inst) {
1092 g_assert (!iresult->declaring->klass->generic_class);
1093 if (iresult->declaring->klass->generic_container)
1094 iresult->context.class_inst = iresult->declaring->klass->generic_container->context.class_inst;
1095 else if (iresult->declaring->klass->generic_class)
1096 iresult->context.class_inst = iresult->declaring->klass->generic_class->context.class_inst;
1098 /* This can happen with some callers like mono_object_get_virtual_method () */
1099 if (!iresult->declaring->klass->generic_container && !iresult->declaring->klass->generic_class)
1100 iresult->context.class_inst = NULL;
1102 MonoImageSet *set = mono_metadata_get_image_set_for_method (iresult);
1105 mono_image_set_lock (set);
1106 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1107 mono_image_set_unlock (set);
1111 return (MonoMethod*)cached;
1114 mono_stats.inflated_method_count++;
1116 inflated_methods_size += sizeof (MonoMethodInflated);
1118 sig = mono_method_signature (method);
1120 char *name = mono_type_get_full_name (method->klass);
1121 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1127 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1129 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1132 result = (MonoMethod *) iresult;
1133 result->is_inflated = TRUE;
1134 result->is_generic = FALSE;
1135 result->sre_method = FALSE;
1136 result->signature = NULL;
1138 if (method->wrapper_type) {
1139 MonoMethodWrapper *mw = (MonoMethodWrapper*)method;
1140 MonoMethodWrapper *resw = (MonoMethodWrapper*)result;
1141 int len = GPOINTER_TO_INT (((void**)mw->method_data) [0]);
1143 resw->method_data = (void **)g_malloc (sizeof (gpointer) * (len + 1));
1144 memcpy (resw->method_data, mw->method_data, sizeof (gpointer) * (len + 1));
1147 if (iresult->context.method_inst) {
1148 /* Set the generic_container of the result to the generic_container of method */
1149 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1151 if (generic_container && iresult->context.method_inst == generic_container->context.method_inst) {
1152 result->is_generic = 1;
1153 mono_method_set_generic_container (result, generic_container);
1157 if (!klass_hint || !klass_hint->generic_class ||
1158 klass_hint->generic_class->container_class != method->klass ||
1159 klass_hint->generic_class->context.class_inst != context->class_inst)
1162 if (method->klass->generic_container)
1163 result->klass = klass_hint;
1165 if (!result->klass) {
1166 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1167 if (!mono_error_ok (error))
1170 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1172 mono_metadata_free_type (inflated);
1176 * FIXME: This should hold, but it doesn't:
1178 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1179 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1180 * g_assert (result->is_generic);
1183 * Fixing this here causes other things to break, hence a very
1184 * ugly hack in mini-trampolines.c - see
1185 * is_generic_method_definition().
1189 mono_image_set_lock (set);
1190 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1192 g_hash_table_insert (set->gmethod_cache, iresult, iresult);
1193 iresult->owner = set;
1196 mono_image_set_unlock (set);
1198 return (MonoMethod*)cached;
1206 * mono_get_inflated_method:
1208 * Obsolete. We keep it around since it's mentioned in the public API.
1211 mono_get_inflated_method (MonoMethod *method)
1217 * mono_method_get_context_general:
1219 * @uninflated: handle uninflated methods?
1221 * Returns the generic context of a method or NULL if it doesn't have
1222 * one. For an inflated method that's the context stored in the
1223 * method. Otherwise it's in the method's generic container or in the
1224 * generic container of the method's class.
1227 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1229 if (method->is_inflated) {
1230 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1231 return &imethod->context;
1235 if (method->is_generic)
1236 return &(mono_method_get_generic_container (method)->context);
1237 if (method->klass->generic_container)
1238 return &method->klass->generic_container->context;
1243 * mono_method_get_context:
1246 * Returns the generic context for method if it's inflated, otherwise
1250 mono_method_get_context (MonoMethod *method)
1252 return mono_method_get_context_general (method, FALSE);
1256 * mono_method_get_generic_container:
1258 * Returns the generic container of METHOD, which should be a generic method definition.
1259 * Returns NULL if METHOD is not a generic method definition.
1260 * LOCKING: Acquires the loader lock.
1262 MonoGenericContainer*
1263 mono_method_get_generic_container (MonoMethod *method)
1265 MonoGenericContainer *container;
1267 if (!method->is_generic)
1270 container = (MonoGenericContainer *)mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1271 g_assert (container);
1277 * mono_method_set_generic_container:
1279 * Sets the generic container of METHOD to CONTAINER.
1280 * LOCKING: Acquires the image lock.
1283 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1285 g_assert (method->is_generic);
1287 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1291 * mono_class_find_enum_basetype:
1292 * @class: The enum class
1294 * Determine the basetype of an enum by iterating through its fields. We do this
1295 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1298 mono_class_find_enum_basetype (MonoClass *klass, MonoError *error)
1300 MonoGenericContainer *container = NULL;
1301 MonoImage *m = klass->image;
1302 const int top = klass->field.count;
1305 g_assert (klass->enumtype);
1307 mono_error_init (error);
1309 if (klass->generic_container)
1310 container = klass->generic_container;
1311 else if (klass->generic_class) {
1312 MonoClass *gklass = klass->generic_class->container_class;
1314 container = gklass->generic_container;
1315 g_assert (container);
1319 * Fetch all the field information.
1321 for (i = 0; i < top; i++){
1323 guint32 cols [MONO_FIELD_SIZE];
1324 int idx = klass->field.first + i;
1327 /* klass->field.first and idx points into the fieldptr table */
1328 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1330 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1333 if (!mono_verifier_verify_field_signature (klass->image, cols [MONO_FIELD_SIGNATURE], NULL)) {
1334 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x", cols [MONO_FIELD_SIGNATURE]);
1338 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1339 mono_metadata_decode_value (sig, &sig);
1340 /* FIELD signature == 0x06 */
1342 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig);
1346 ftype = mono_metadata_parse_type_checked (m, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
1350 if (klass->generic_class) {
1351 //FIXME do we leak here?
1352 ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (klass), error);
1353 if (!mono_error_ok (error))
1355 ftype->attrs = cols [MONO_FIELD_FLAGS];
1360 mono_error_set_type_load_class (error, klass, "Could not find base type");
1367 * Checks for MonoClass::exception_type without resolving all MonoType's into MonoClass'es
1370 mono_type_has_exceptions (MonoType *type)
1372 switch (type->type) {
1373 case MONO_TYPE_CLASS:
1374 case MONO_TYPE_VALUETYPE:
1375 case MONO_TYPE_SZARRAY:
1376 return mono_class_has_failure (type->data.klass);
1377 case MONO_TYPE_ARRAY:
1378 return mono_class_has_failure (type->data.array->eklass);
1379 case MONO_TYPE_GENERICINST:
1380 return mono_class_has_failure (mono_generic_class_get_class (type->data.generic_class));
1387 mono_error_set_for_class_failure (MonoError *oerror, MonoClass *klass)
1389 gpointer exception_data = mono_class_get_exception_data (klass);
1391 switch (mono_class_get_failure(klass)) {
1392 case MONO_EXCEPTION_TYPE_LOAD:
1393 case MONO_EXCEPTION_INVALID_PROGRAM: {
1394 MonoErrorBoxed *box = (MonoErrorBoxed*)exception_data;
1395 mono_error_set_from_boxed (oerror, box);
1398 case MONO_EXCEPTION_MISSING_METHOD:
1399 case MONO_EXCEPTION_MISSING_FIELD:
1400 case MONO_EXCEPTION_FILE_NOT_FOUND:
1401 case MONO_EXCEPTION_BAD_IMAGE:
1403 g_assert_not_reached ();
1411 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1415 mono_class_alloc (MonoClass *klass, int size)
1417 if (klass->generic_class)
1418 return mono_image_set_alloc (klass->generic_class->owner, size);
1420 return mono_image_alloc (klass->image, size);
1424 mono_class_alloc0 (MonoClass *klass, int size)
1428 res = mono_class_alloc (klass, size);
1429 memset (res, 0, size);
1433 #define mono_class_new0(klass,struct_type, n_structs) \
1434 ((struct_type *) mono_class_alloc0 ((klass), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1437 * mono_class_setup_basic_field_info:
1438 * @class: The class to initialize
1440 * Initializes the klass->fields.
1441 * LOCKING: Assumes the loader lock is held.
1444 mono_class_setup_basic_field_info (MonoClass *klass)
1446 MonoClassField *field;
1454 gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
1455 image = klass->image;
1456 top = klass->field.count;
1458 if (klass->generic_class && image_is_dynamic (klass->generic_class->container_class->image) && !klass->generic_class->container_class->wastypebuilder) {
1460 * This happens when a generic instance of an unfinished generic typebuilder
1461 * is used as an element type for creating an array type. We can't initialize
1462 * the fields of this class using the fields of gklass, since gklass is not
1463 * finished yet, fields could be added to it later.
1469 mono_class_setup_basic_field_info (gtd);
1471 top = gtd->field.count;
1472 klass->field.first = gtd->field.first;
1473 klass->field.count = gtd->field.count;
1476 klass->fields = (MonoClassField *)mono_class_alloc0 (klass, sizeof (MonoClassField) * top);
1479 * Fetch all the field information.
1481 for (i = 0; i < top; i++){
1482 field = &klass->fields [i];
1483 field->parent = klass;
1486 field->name = mono_field_get_name (>d->fields [i]);
1488 int idx = klass->field.first + i;
1489 /* klass->field.first and idx points into the fieldptr table */
1490 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1491 /* The name is needed for fieldrefs */
1492 field->name = mono_metadata_string_heap (image, name_idx);
1498 * mono_class_setup_fields:
1499 * @class: The class to initialize
1501 * Initializes the klass->fields.
1502 * LOCKING: Assumes the loader lock is held.
1505 mono_class_setup_fields (MonoClass *klass)
1508 MonoImage *m = klass->image;
1510 guint32 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1511 int i, blittable = TRUE;
1512 guint32 real_size = 0;
1513 guint32 packing_size = 0;
1515 gboolean explicit_size;
1516 MonoClassField *field;
1517 MonoGenericContainer *container = NULL;
1518 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
1521 * FIXME: We have a race condition here. It's possible that this function returns
1522 * to its caller with `instance_size` set to `0` instead of the actual size. This
1523 * is not a problem when the function is called recursively on the same class,
1524 * because the size will be initialized by the outer invocation. What follows is a
1525 * description of how it can occur in other cases, too. There it is a problem,
1526 * because it can lead to the GC being asked to allocate an object of size `0`,
1527 * which SGen chokes on. The race condition is triggered infrequently by
1528 * `tests/sgen-suspend.cs`.
1530 * This function is called for a class whenever one of its subclasses is inited.
1531 * For example, it's called for every subclass of Object. What it does is this:
1533 * if (klass->setup_fields_called)
1536 * klass->instance_size = 0;
1538 * klass->setup_fields_called = 1;
1539 * ... critical point
1540 * klass->instance_size = actual_instance_size;
1542 * The last two steps are sometimes reversed, but that only changes the way in which
1543 * the race condition works.
1545 * Assume thread A goes through this function and makes it to the critical point.
1546 * Now thread B runs the function and, since `setup_fields_called` is set, returns
1547 * immediately, but `instance_size` is incorrect.
1549 * The other case looks like this:
1551 * if (klass->setup_fields_called)
1553 * ... critical point X
1554 * klass->instance_size = 0;
1555 * ... critical point Y
1556 * klass->instance_size = actual_instance_size;
1558 * klass->setup_fields_called = 1;
1560 * Assume thread A goes through the function and makes it to critical point X. Now
1561 * thread B runs through the whole of the function, returning, assuming
1562 * `instance_size` is set. At that point thread A gets to run and makes it to
1563 * critical point Y, at which time `instance_size` is `0` again, invalidating thread
1566 if (klass->setup_fields_called)
1569 if (klass->generic_class && image_is_dynamic (klass->generic_class->container_class->image) && !klass->generic_class->container_class->wastypebuilder) {
1571 * This happens when a generic instance of an unfinished generic typebuilder
1572 * is used as an element type for creating an array type. We can't initialize
1573 * the fields of this class using the fields of gklass, since gklass is not
1574 * finished yet, fields could be added to it later.
1579 mono_class_setup_basic_field_info (klass);
1580 top = klass->field.count;
1583 mono_class_setup_fields (gtd);
1584 if (mono_class_has_failure (gtd)) {
1585 mono_class_set_type_load_failure (klass, "");
1592 klass->sizes.class_size = 0;
1594 if (klass->parent) {
1595 /* For generic instances, klass->parent might not have been initialized */
1596 mono_class_init (klass->parent);
1597 if (!klass->parent->size_inited) {
1598 mono_class_setup_fields (klass->parent);
1599 if (mono_class_has_failure (klass->parent)) {
1600 mono_class_set_type_load_failure (klass, "");
1604 instance_size += klass->parent->instance_size;
1605 klass->min_align = klass->parent->min_align;
1606 /* we use |= since it may have been set already */
1607 klass->has_references |= klass->parent->has_references;
1608 blittable = klass->parent->blittable;
1610 instance_size = sizeof (MonoObject);
1611 klass->min_align = 1;
1614 /* We can't really enable 16 bytes alignment until the GC supports it.
1615 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1616 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1617 Bug #506144 is an example of this issue.
1619 if (klass->simd_type)
1620 klass->min_align = 16;
1622 /* Get the real size */
1623 explicit_size = mono_metadata_packing_from_typedef (klass->image, klass->type_token, &packing_size, &real_size);
1625 if (explicit_size) {
1626 if ((packing_size & 0xffffff00) != 0) {
1627 mono_class_set_type_load_failure (klass, "Could not load struct '%s' with packing size %d >= 256", klass->name, packing_size);
1630 klass->packing_size = packing_size;
1631 real_size += instance_size;
1635 if (explicit_size && real_size) {
1636 instance_size = MAX (real_size, instance_size);
1638 klass->blittable = blittable;
1639 if (!klass->instance_size)
1640 klass->instance_size = instance_size;
1641 mono_memory_barrier ();
1642 klass->size_inited = 1;
1643 klass->fields_inited = 1;
1644 klass->setup_fields_called = 1;
1648 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(mono_is_corlib_image (klass->image) && !strcmp (klass->name_space, "System") && !strcmp (klass->name, "ValueType")))
1651 /* Prevent infinite loops if the class references itself */
1652 klass->setup_fields_called = 1;
1654 if (klass->generic_container) {
1655 container = klass->generic_container;
1657 container = gtd->generic_container;
1658 g_assert (container);
1662 * Fetch all the field information.
1664 for (i = 0; i < top; i++){
1665 int idx = klass->field.first + i;
1666 field = &klass->fields [i];
1668 field->parent = klass;
1671 mono_field_resolve_type (field, &error);
1672 if (!mono_error_ok (&error)) {
1673 /*mono_field_resolve_type already failed class*/
1674 mono_error_cleanup (&error);
1678 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(klass), field->name);
1679 g_assert (field->type);
1682 if (mono_field_is_deleted (field))
1685 MonoClassField *gfield = >d->fields [i];
1686 field->offset = gfield->offset;
1688 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1690 mono_metadata_field_info (m, idx, &offset, NULL, NULL);
1691 field->offset = offset;
1693 if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1694 mono_class_set_type_load_failure (klass, "Missing field layout info for %s", field->name);
1697 if (field->offset < -1) { /*-1 is used to encode special static fields */
1698 mono_class_set_type_load_failure (klass, "Invalid negative field offset %d for %s", field->offset, field->name);
1701 if (klass->generic_container) {
1702 mono_class_set_type_load_failure (klass, "Generic class cannot have explicit layout.");
1708 /* Only do these checks if we still think this type is blittable */
1709 if (blittable && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1710 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1713 MonoClass *field_class = mono_class_from_mono_type (field->type);
1715 mono_class_setup_fields (field_class);
1716 if (mono_class_has_failure (field_class)) {
1717 mono_class_set_type_load_failure (klass, "");
1721 if (!field_class || !field_class->blittable)
1726 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1727 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
1728 blittable = klass->element_class->blittable;
1731 if (mono_type_has_exceptions (field->type)) {
1732 char *class_name = mono_type_get_full_name (klass);
1733 char *type_name = mono_type_full_name (field->type);
1735 mono_class_set_type_load_failure (klass, "");
1736 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1737 g_free (class_name);
1741 /* The def_value of fields is compute lazily during vtable creation */
1744 if (klass == mono_defaults.string_class)
1747 klass->blittable = blittable;
1749 if (klass->enumtype && !mono_class_enum_basetype (klass)) {
1750 mono_class_set_type_load_failure (klass, "");
1753 if (explicit_size && real_size) {
1754 instance_size = MAX (real_size, instance_size);
1757 if (mono_class_has_failure (klass))
1759 mono_class_layout_fields (klass, instance_size);
1761 /*valuetypes can't be neither bigger than 1Mb or empty. */
1762 if (klass->valuetype && (klass->instance_size <= 0 || klass->instance_size > (0x100000 + sizeof (MonoObject))))
1763 mono_class_set_type_load_failure (klass, "");
1765 mono_memory_barrier ();
1766 klass->fields_inited = 1;
1770 * mono_class_setup_fields_locking:
1771 * @class: The class to initialize
1773 * Initializes the klass->fields array of fields.
1774 * Aquires the loader lock.
1777 mono_class_setup_fields_locking (MonoClass *klass)
1779 /* This can be checked without locks */
1780 if (klass->fields_inited)
1782 mono_loader_lock ();
1783 mono_class_setup_fields (klass);
1784 mono_loader_unlock ();
1788 * mono_class_has_references:
1790 * Returns whenever @klass->has_references is set, initializing it if needed.
1791 * Aquires the loader lock.
1794 mono_class_has_references (MonoClass *klass)
1796 if (klass->init_pending) {
1797 /* Be conservative */
1800 mono_class_init (klass);
1802 return klass->has_references;
1807 * mono_type_get_basic_type_from_generic:
1810 * Returns a closed type corresponding to the possibly open type
1814 mono_type_get_basic_type_from_generic (MonoType *type)
1816 /* When we do generic sharing we let type variables stand for reference/primitive types. */
1817 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) &&
1818 (!type->data.generic_param->gshared_constraint || type->data.generic_param->gshared_constraint->type == MONO_TYPE_OBJECT))
1819 return &mono_defaults.object_class->byval_arg;
1824 type_has_references (MonoClass *klass, MonoType *ftype)
1826 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (klass, ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1828 if (!ftype->byref && (ftype->type == MONO_TYPE_VAR || ftype->type == MONO_TYPE_MVAR)) {
1829 MonoGenericParam *gparam = ftype->data.generic_param;
1831 if (gparam->gshared_constraint)
1832 return mono_class_has_references (mono_class_from_mono_type (gparam->gshared_constraint));
1838 * mono_class_layout_fields:
1840 * @instance_size: base instance size
1842 * Compute the placement of fields inside an object or struct, according to
1843 * the layout rules and set the following fields in @class:
1844 * - has_references (if the class contains instance references firled or structs that contain references)
1845 * - has_static_refs (same, but for static fields)
1846 * - instance_size (size of the object in memory)
1847 * - class_size (size needed for the static fields)
1848 * - size_inited (flag set when the instance_size is set)
1850 * LOCKING: this is supposed to be called with the loader lock held.
1853 mono_class_layout_fields (MonoClass *klass, int instance_size)
1856 const int top = klass->field.count;
1857 guint32 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1858 guint32 pass, passes, real_size;
1859 gboolean gc_aware_layout = FALSE;
1860 gboolean has_static_fields = FALSE;
1861 MonoClassField *field;
1864 * When we do generic sharing we need to have layout
1865 * information for open generic classes (either with a generic
1866 * context containing type variables or with a generic
1867 * container), so we don't return in that case anymore.
1871 * Enable GC aware auto layout: in this mode, reference
1872 * fields are grouped together inside objects, increasing collector
1874 * Requires that all classes whose layout is known to native code be annotated
1875 * with [StructLayout (LayoutKind.Sequential)]
1876 * Value types have gc_aware_layout disabled by default, as per
1877 * what the default is for other runtimes.
1879 /* corlib is missing [StructLayout] directives in many places */
1880 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1881 if (!klass->valuetype)
1882 gc_aware_layout = TRUE;
1885 /* Compute klass->has_references */
1887 * Process non-static fields first, since static fields might recursively
1888 * refer to the class itself.
1890 for (i = 0; i < top; i++) {
1893 field = &klass->fields [i];
1895 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1896 ftype = mono_type_get_underlying_type (field->type);
1897 ftype = mono_type_get_basic_type_from_generic (ftype);
1898 if (type_has_references (klass, ftype))
1899 klass->has_references = TRUE;
1903 for (i = 0; i < top; i++) {
1906 field = &klass->fields [i];
1908 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1909 ftype = mono_type_get_underlying_type (field->type);
1910 ftype = mono_type_get_basic_type_from_generic (ftype);
1911 if (type_has_references (klass, ftype))
1912 klass->has_static_refs = TRUE;
1916 for (i = 0; i < top; i++) {
1919 field = &klass->fields [i];
1921 ftype = mono_type_get_underlying_type (field->type);
1922 ftype = mono_type_get_basic_type_from_generic (ftype);
1923 if (type_has_references (klass, ftype)) {
1924 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1925 klass->has_static_refs = TRUE;
1927 klass->has_references = TRUE;
1932 * Compute field layout and total size (not considering static fields)
1935 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1936 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1938 if (gc_aware_layout)
1943 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1946 if (klass->parent) {
1947 mono_class_setup_fields (klass->parent);
1948 if (mono_class_has_failure (klass->parent)) {
1949 mono_class_set_type_load_failure (klass, "");
1952 real_size = klass->parent->instance_size;
1954 real_size = sizeof (MonoObject);
1957 for (pass = 0; pass < passes; ++pass) {
1958 for (i = 0; i < top; i++){
1963 field = &klass->fields [i];
1965 if (mono_field_is_deleted (field))
1967 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1970 ftype = mono_type_get_underlying_type (field->type);
1971 ftype = mono_type_get_basic_type_from_generic (ftype);
1972 if (gc_aware_layout) {
1973 if (type_has_references (klass, ftype)) {
1982 if ((top == 1) && (klass->instance_size == sizeof (MonoObject)) &&
1983 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1984 /* This field is a hack inserted by MCS to empty structures */
1988 size = mono_type_size (field->type, &align);
1990 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1991 align = klass->packing_size ? MIN (klass->packing_size, align): align;
1992 /* if the field has managed references, we need to force-align it
1995 if (type_has_references (klass, ftype))
1996 align = MAX (align, sizeof (gpointer));
1998 klass->min_align = MAX (align, klass->min_align);
1999 field->offset = real_size;
2001 field->offset += align - 1;
2002 field->offset &= ~(align - 1);
2004 /*TypeBuilders produce all sort of weird things*/
2005 g_assert (image_is_dynamic (klass->image) || field->offset > 0);
2006 real_size = field->offset + size;
2009 instance_size = MAX (real_size, instance_size);
2011 if (instance_size & (klass->min_align - 1)) {
2012 instance_size += klass->min_align - 1;
2013 instance_size &= ~(klass->min_align - 1);
2017 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
2021 for (i = 0; i < top; i++) {
2026 field = &klass->fields [i];
2029 * There must be info about all the fields in a type if it
2030 * uses explicit layout.
2032 if (mono_field_is_deleted (field))
2034 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2037 size = mono_type_size (field->type, &align);
2038 align = klass->packing_size ? MIN (klass->packing_size, align): align;
2039 klass->min_align = MAX (align, klass->min_align);
2042 * When we get here, field->offset is already set by the
2043 * loader (for either runtime fields or fields loaded from metadata).
2044 * The offset is from the start of the object: this works for both
2045 * classes and valuetypes.
2047 field->offset += sizeof (MonoObject);
2048 ftype = mono_type_get_underlying_type (field->type);
2049 ftype = mono_type_get_basic_type_from_generic (ftype);
2050 if (type_has_references (klass, ftype)) {
2051 if (field->offset % sizeof (gpointer)) {
2052 mono_class_set_type_load_failure (klass, "");
2059 real_size = MAX (real_size, size + field->offset);
2062 if (klass->has_references) {
2063 ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
2065 /* Check for overlapping reference and non-reference fields */
2066 for (i = 0; i < top; i++) {
2069 field = &klass->fields [i];
2071 if (mono_field_is_deleted (field))
2073 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2075 ftype = mono_type_get_underlying_type (field->type);
2076 if (MONO_TYPE_IS_REFERENCE (ftype))
2077 ref_bitmap [field->offset / sizeof (gpointer)] = 1;
2079 for (i = 0; i < top; i++) {
2080 field = &klass->fields [i];
2082 if (mono_field_is_deleted (field))
2084 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2087 // FIXME: Too much code does this
2089 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field->offset / sizeof (gpointer)]) {
2090 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->offset);
2094 g_free (ref_bitmap);
2097 instance_size = MAX (real_size, instance_size);
2098 if (instance_size & (klass->min_align - 1)) {
2099 instance_size += klass->min_align - 1;
2100 instance_size &= ~(klass->min_align - 1);
2106 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2108 * This leads to all kinds of problems with nested structs, so only
2109 * enable it when a MONO_DEBUG property is set.
2111 * For small structs, set min_align to at least the struct size to improve
2112 * performance, and since the JIT memset/memcpy code assumes this and generates
2113 * unaligned accesses otherwise. See #78990 for a testcase.
2115 if (mono_align_small_structs) {
2116 if (instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2117 klass->min_align = MAX (klass->min_align, instance_size - sizeof (MonoObject));
2121 if (klass->instance_size && !klass->image->dynamic) {
2122 /* Might be already set using cached info */
2123 g_assert (klass->instance_size == instance_size);
2125 klass->instance_size = instance_size;
2127 mono_memory_barrier ();
2128 klass->size_inited = 1;
2131 * Compute static field layout and size
2133 for (i = 0; i < top; i++){
2137 field = &klass->fields [i];
2139 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2141 if (mono_field_is_deleted (field))
2144 if (mono_type_has_exceptions (field->type)) {
2145 mono_class_set_type_load_failure (klass, "");
2149 has_static_fields = TRUE;
2151 size = mono_type_size (field->type, &align);
2152 field->offset = klass->sizes.class_size;
2153 /*align is always non-zero here*/
2154 field->offset += align - 1;
2155 field->offset &= ~(align - 1);
2156 klass->sizes.class_size = field->offset + size;
2159 if (has_static_fields && klass->sizes.class_size == 0)
2160 /* Simplify code which depends on class_size != 0 if the class has static fields */
2161 klass->sizes.class_size = 8;
2165 create_array_method (MonoClass *klass, const char *name, MonoMethodSignature *sig)
2169 method = (MonoMethod *) mono_image_alloc0 (klass->image, sizeof (MonoMethodPInvoke));
2170 method->klass = klass;
2171 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2172 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2173 method->signature = sig;
2174 method->name = name;
2177 if (name [0] == '.') {
2178 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2180 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2186 * mono_class_setup_methods:
2189 * Initializes the 'methods' array in CLASS.
2190 * Calling this method should be avoided if possible since it allocates a lot
2191 * of long-living MonoMethod structures.
2192 * Methods belonging to an interface are assigned a sequential slot starting
2195 * On failure this function sets klass->exception_type
2198 mono_class_setup_methods (MonoClass *klass)
2201 MonoMethod **methods;
2206 if (klass->generic_class) {
2208 MonoClass *gklass = klass->generic_class->container_class;
2210 mono_class_init (gklass);
2211 if (!mono_class_has_failure (gklass))
2212 mono_class_setup_methods (gklass);
2213 if (mono_class_has_failure (gklass)) {
2214 /* FIXME make exception_data less opaque so it's possible to dup it here */
2215 mono_class_set_type_load_failure (klass, "Generic type definition failed to load");
2219 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2220 count = gklass->method.count;
2221 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * (count + 1));
2223 for (i = 0; i < count; i++) {
2224 methods [i] = mono_class_inflate_generic_method_full_checked (
2225 gklass->methods [i], klass, mono_class_get_context (klass), &error);
2226 if (!mono_error_ok (&error)) {
2227 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2228 mono_class_set_type_load_failure (klass, "Could not inflate method %s due to %s", method, mono_error_get_message (&error));
2231 mono_error_cleanup (&error);
2235 } else if (klass->rank) {
2237 MonoMethod *amethod;
2238 MonoMethodSignature *sig;
2239 int count_generic = 0, first_generic = 0;
2241 gboolean jagged_ctor = FALSE;
2243 count = 3 + (klass->rank > 1? 2: 1);
2245 mono_class_setup_interfaces (klass, &error);
2246 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2248 if (klass->rank == 1 && klass->element_class->rank) {
2250 klass->method.count ++;
2253 if (klass->interface_count) {
2254 count_generic = generic_array_methods (klass);
2255 first_generic = count;
2256 count += klass->interface_count * count_generic;
2259 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * count);
2261 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2262 sig->ret = &mono_defaults.void_class->byval_arg;
2263 sig->pinvoke = TRUE;
2264 sig->hasthis = TRUE;
2265 for (i = 0; i < klass->rank; ++i)
2266 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2268 amethod = create_array_method (klass, ".ctor", sig);
2269 methods [method_num++] = amethod;
2270 if (klass->rank > 1) {
2271 sig = mono_metadata_signature_alloc (klass->image, klass->rank * 2);
2272 sig->ret = &mono_defaults.void_class->byval_arg;
2273 sig->pinvoke = TRUE;
2274 sig->hasthis = TRUE;
2275 for (i = 0; i < klass->rank * 2; ++i)
2276 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2278 amethod = create_array_method (klass, ".ctor", sig);
2279 methods [method_num++] = amethod;
2283 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2284 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2285 sig->ret = &mono_defaults.void_class->byval_arg;
2286 sig->pinvoke = TRUE;
2287 sig->hasthis = TRUE;
2288 for (i = 0; i < klass->rank + 1; ++i)
2289 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2290 amethod = create_array_method (klass, ".ctor", sig);
2291 methods [method_num++] = amethod;
2294 /* element Get (idx11, [idx2, ...]) */
2295 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2296 sig->ret = &klass->element_class->byval_arg;
2297 sig->pinvoke = TRUE;
2298 sig->hasthis = TRUE;
2299 for (i = 0; i < klass->rank; ++i)
2300 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2301 amethod = create_array_method (klass, "Get", sig);
2302 methods [method_num++] = amethod;
2303 /* element& Address (idx11, [idx2, ...]) */
2304 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2305 sig->ret = &klass->element_class->this_arg;
2306 sig->pinvoke = TRUE;
2307 sig->hasthis = TRUE;
2308 for (i = 0; i < klass->rank; ++i)
2309 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2310 amethod = create_array_method (klass, "Address", sig);
2311 methods [method_num++] = amethod;
2312 /* void Set (idx11, [idx2, ...], element) */
2313 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2314 sig->ret = &mono_defaults.void_class->byval_arg;
2315 sig->pinvoke = TRUE;
2316 sig->hasthis = TRUE;
2317 for (i = 0; i < klass->rank; ++i)
2318 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2319 sig->params [i] = &klass->element_class->byval_arg;
2320 amethod = create_array_method (klass, "Set", sig);
2321 methods [method_num++] = amethod;
2323 for (i = 0; i < klass->interface_count; i++)
2324 setup_generic_array_ifaces (klass, klass->interfaces [i], methods, first_generic + i * count_generic);
2328 count = klass->method.count;
2329 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * count);
2330 for (i = 0; i < count; ++i) {
2331 int idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_METHOD, klass->method.first + i + 1);
2332 methods [i] = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | idx, klass, NULL, &error);
2334 mono_class_set_type_load_failure (klass, "Could not load method %d due to %s", i, mono_error_get_message (&error));
2335 mono_error_cleanup (&error);
2340 if (MONO_CLASS_IS_INTERFACE (klass)) {
2342 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2343 for (i = 0; i < count; ++i) {
2344 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2345 methods [i]->slot = slot++;
2349 mono_image_lock (klass->image);
2351 if (!klass->methods) {
2352 klass->method.count = count;
2354 /* Needed because of the double-checking locking pattern */
2355 mono_memory_barrier ();
2357 klass->methods = methods;
2360 mono_image_unlock (klass->image);
2364 * mono_class_get_method_by_index:
2366 * Returns klass->methods [index], initializing klass->methods if neccesary.
2368 * LOCKING: Acquires the loader lock.
2371 mono_class_get_method_by_index (MonoClass *klass, int index)
2374 /* Avoid calling setup_methods () if possible */
2375 if (klass->generic_class && !klass->methods) {
2376 MonoClass *gklass = klass->generic_class->container_class;
2379 m = mono_class_inflate_generic_method_full_checked (
2380 gklass->methods [index], klass, mono_class_get_context (klass), &error);
2381 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2383 * If setup_methods () is called later for this class, no duplicates are created,
2384 * since inflate_generic_method guarantees that only one instance of a method
2385 * is created for each context.
2388 mono_class_setup_methods (klass);
2389 g_assert (m == klass->methods [index]);
2393 mono_class_setup_methods (klass);
2394 if (mono_class_has_failure (klass)) /*FIXME do proper error handling*/
2396 g_assert (index >= 0 && index < klass->method.count);
2397 return klass->methods [index];
2402 * mono_class_get_inflated_method:
2404 * Given an inflated class CLASS and a method METHOD which should be a method of
2405 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2408 mono_class_get_inflated_method (MonoClass *klass, MonoMethod *method)
2410 MonoClass *gklass = klass->generic_class->container_class;
2413 g_assert (method->klass == gklass);
2415 mono_class_setup_methods (gklass);
2416 g_assert (!mono_class_has_failure (gklass)); /*FIXME do proper error handling*/
2418 for (i = 0; i < gklass->method.count; ++i) {
2419 if (gklass->methods [i] == method) {
2420 if (klass->methods) {
2421 return klass->methods [i];
2424 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], klass, mono_class_get_context (klass), &error);
2425 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2435 * mono_class_get_vtable_entry:
2437 * Returns klass->vtable [offset], computing it if neccesary. Returns NULL on failure.
2438 * LOCKING: Acquires the loader lock.
2441 mono_class_get_vtable_entry (MonoClass *klass, int offset)
2445 if (klass->rank == 1) {
2447 * szarrays do not overwrite any methods of Array, so we can avoid
2448 * initializing their vtables in some cases.
2450 mono_class_setup_vtable (klass->parent);
2451 if (offset < klass->parent->vtable_size)
2452 return klass->parent->vtable [offset];
2455 if (klass->generic_class) {
2457 MonoClass *gklass = klass->generic_class->container_class;
2458 mono_class_setup_vtable (gklass);
2459 m = gklass->vtable [offset];
2461 m = mono_class_inflate_generic_method_full_checked (m, klass, mono_class_get_context (klass), &error);
2462 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2464 mono_class_setup_vtable (klass);
2465 if (mono_class_has_failure (klass))
2467 m = klass->vtable [offset];
2474 * mono_class_get_vtable_size:
2476 * Return the vtable size for KLASS.
2479 mono_class_get_vtable_size (MonoClass *klass)
2481 mono_class_setup_vtable (klass);
2483 return klass->vtable_size;
2487 * mono_class_setup_properties:
2489 * Initialize klass->ext.property and klass->ext.properties.
2491 * This method can fail the class.
2494 mono_class_setup_properties (MonoClass *klass)
2496 guint startm, endm, i, j;
2497 guint32 cols [MONO_PROPERTY_SIZE];
2498 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2499 MonoProperty *properties;
2503 if (klass->ext && klass->ext->properties)
2506 if (klass->generic_class) {
2507 MonoClass *gklass = klass->generic_class->container_class;
2509 mono_class_init (gklass);
2510 mono_class_setup_properties (gklass);
2511 if (mono_class_has_failure (gklass)) {
2512 mono_class_set_type_load_failure (klass, "Generic type definition failed to load");
2516 properties = mono_class_new0 (klass, MonoProperty, gklass->ext->property.count + 1);
2518 for (i = 0; i < gklass->ext->property.count; i++) {
2520 MonoProperty *prop = &properties [i];
2522 *prop = gklass->ext->properties [i];
2525 prop->get = mono_class_inflate_generic_method_full_checked (
2526 prop->get, klass, mono_class_get_context (klass), &error);
2528 prop->set = mono_class_inflate_generic_method_full_checked (
2529 prop->set, klass, mono_class_get_context (klass), &error);
2531 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2532 prop->parent = klass;
2535 first = gklass->ext->property.first;
2536 count = gklass->ext->property.count;
2538 first = mono_metadata_properties_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2539 count = last - first;
2542 mono_class_setup_methods (klass);
2543 if (mono_class_has_failure (klass))
2547 properties = (MonoProperty *)mono_class_alloc0 (klass, sizeof (MonoProperty) * count);
2548 for (i = first; i < last; ++i) {
2549 mono_metadata_decode_table_row (klass->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2550 properties [i - first].parent = klass;
2551 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2552 properties [i - first].name = mono_metadata_string_heap (klass->image, cols [MONO_PROPERTY_NAME]);
2554 startm = mono_metadata_methods_from_property (klass->image, i, &endm);
2555 for (j = startm; j < endm; ++j) {
2558 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2560 if (klass->image->uncompressed_metadata) {
2562 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2563 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2564 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2566 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - klass->method.first];
2569 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2570 case METHOD_SEMANTIC_SETTER:
2571 properties [i - first].set = method;
2573 case METHOD_SEMANTIC_GETTER:
2574 properties [i - first].get = method;
2583 mono_class_alloc_ext (klass);
2585 mono_image_lock (klass->image);
2587 if (klass->ext->properties) {
2588 /* We leak 'properties' which was allocated from the image mempool */
2589 mono_image_unlock (klass->image);
2593 klass->ext->property.first = first;
2594 klass->ext->property.count = count;
2596 /* Flush any pending writes as we do double checked locking on klass->ext->properties */
2597 mono_memory_barrier ();
2599 /* Leave this assignment as the last op in the function */
2600 klass->ext->properties = properties;
2602 mono_image_unlock (klass->image);
2606 inflate_method_listz (MonoMethod **methods, MonoClass *klass, MonoGenericContext *context)
2608 MonoMethod **om, **retval;
2611 for (om = methods, count = 0; *om; ++om, ++count)
2614 retval = g_new0 (MonoMethod*, count + 1);
2616 for (om = methods, count = 0; *om; ++om, ++count) {
2618 retval [count] = mono_class_inflate_generic_method_full_checked (*om, klass, context, &error);
2619 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2625 /*This method can fail the class.*/
2627 mono_class_setup_events (MonoClass *klass)
2630 guint startm, endm, i, j;
2631 guint32 cols [MONO_EVENT_SIZE];
2632 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2636 if (klass->ext && klass->ext->events)
2639 if (klass->generic_class) {
2640 MonoClass *gklass = klass->generic_class->container_class;
2641 MonoGenericContext *context = NULL;
2643 mono_class_setup_events (gklass);
2644 if (mono_class_has_failure (gklass)) {
2645 mono_class_set_type_load_failure (klass, "Generic type definition failed to load");
2649 first = gklass->ext->event.first;
2650 count = gklass->ext->event.count;
2652 events = mono_class_new0 (klass, MonoEvent, count);
2655 context = mono_class_get_context (klass);
2657 for (i = 0; i < count; i++) {
2659 MonoEvent *event = &events [i];
2660 MonoEvent *gevent = &gklass->ext->events [i];
2662 mono_error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2664 event->parent = klass;
2665 event->name = gevent->name;
2666 event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, klass, context, &error) : NULL;
2667 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2668 event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, klass, context, &error) : NULL;
2669 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2670 event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, klass, context, &error) : NULL;
2671 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2673 #ifndef MONO_SMALL_CONFIG
2674 event->other = gevent->other ? inflate_method_listz (gevent->other, klass, context) : NULL;
2676 event->attrs = gevent->attrs;
2679 first = mono_metadata_events_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2680 count = last - first;
2683 mono_class_setup_methods (klass);
2684 if (mono_class_has_failure (klass)) {
2685 mono_class_set_type_load_failure (klass, "Generic type definition failed to load");
2690 events = (MonoEvent *)mono_class_alloc0 (klass, sizeof (MonoEvent) * count);
2691 for (i = first; i < last; ++i) {
2692 MonoEvent *event = &events [i - first];
2694 mono_metadata_decode_table_row (klass->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2695 event->parent = klass;
2696 event->attrs = cols [MONO_EVENT_FLAGS];
2697 event->name = mono_metadata_string_heap (klass->image, cols [MONO_EVENT_NAME]);
2699 startm = mono_metadata_methods_from_event (klass->image, i, &endm);
2700 for (j = startm; j < endm; ++j) {
2703 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2705 if (klass->image->uncompressed_metadata) {
2707 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2708 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2709 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2711 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - klass->method.first];
2714 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2715 case METHOD_SEMANTIC_ADD_ON:
2716 event->add = method;
2718 case METHOD_SEMANTIC_REMOVE_ON:
2719 event->remove = method;
2721 case METHOD_SEMANTIC_FIRE:
2722 event->raise = method;
2724 case METHOD_SEMANTIC_OTHER: {
2725 #ifndef MONO_SMALL_CONFIG
2728 if (event->other == NULL) {
2729 event->other = g_new0 (MonoMethod*, 2);
2731 while (event->other [n])
2733 event->other = (MonoMethod **)g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2735 event->other [n] = method;
2736 /* NULL terminated */
2737 event->other [n + 1] = NULL;
2748 mono_class_alloc_ext (klass);
2750 mono_image_lock (klass->image);
2752 if (klass->ext->events) {
2753 mono_image_unlock (klass->image);
2757 klass->ext->event.first = first;
2758 klass->ext->event.count = count;
2760 /* Flush any pending writes as we do double checked locking on klass->ext.events */
2761 mono_memory_barrier ();
2763 /* Leave this assignment as the last op in the function */
2764 klass->ext->events = events;
2766 mono_image_unlock (klass->image);
2770 * Global pool of interface IDs, represented as a bitset.
2771 * LOCKING: Protected by the classes lock.
2773 static MonoBitSet *global_interface_bitset = NULL;
2776 * mono_unload_interface_ids:
2777 * @bitset: bit set of interface IDs
2779 * When an image is unloaded, the interface IDs associated with
2780 * the image are put back in the global pool of IDs so the numbers
2784 mono_unload_interface_ids (MonoBitSet *bitset)
2787 mono_bitset_sub (global_interface_bitset, bitset);
2792 mono_unload_interface_id (MonoClass *klass)
2794 if (global_interface_bitset && klass->interface_id) {
2796 mono_bitset_clear (global_interface_bitset, klass->interface_id);
2802 * mono_get_unique_iid:
2805 * Assign a unique integer ID to the interface represented by @class.
2806 * The ID will positive and as small as possible.
2807 * LOCKING: Acquires the classes lock.
2808 * Returns: The new ID.
2811 mono_get_unique_iid (MonoClass *klass)
2815 g_assert (MONO_CLASS_IS_INTERFACE (klass));
2819 if (!global_interface_bitset) {
2820 global_interface_bitset = mono_bitset_new (128, 0);
2823 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2825 int old_size = mono_bitset_size (global_interface_bitset);
2826 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2827 mono_bitset_free (global_interface_bitset);
2828 global_interface_bitset = new_set;
2831 mono_bitset_set (global_interface_bitset, iid);
2832 /* set the bit also in the per-image set */
2833 if (!klass->generic_class) {
2834 if (klass->image->interface_bitset) {
2835 if (iid >= mono_bitset_size (klass->image->interface_bitset)) {
2836 MonoBitSet *new_set = mono_bitset_clone (klass->image->interface_bitset, iid + 1);
2837 mono_bitset_free (klass->image->interface_bitset);
2838 klass->image->interface_bitset = new_set;
2841 klass->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2843 mono_bitset_set (klass->image->interface_bitset, iid);
2848 #ifndef MONO_SMALL_CONFIG
2849 if (mono_print_vtable) {
2851 char *type_name = mono_type_full_name (&klass->byval_arg);
2852 if (klass->generic_class && !klass->generic_class->context.class_inst->is_open) {
2853 generic_id = klass->generic_class->context.class_inst->id;
2854 g_assert (generic_id != 0);
2858 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, klass->image->name, type_name, generic_id);
2863 g_assert (iid <= 65535);
2868 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2873 mono_class_setup_interfaces (klass, error);
2874 return_if_nok (error);
2876 for (i = 0; i < klass->interface_count; i++) {
2877 ic = klass->interfaces [i];
2880 *res = g_ptr_array_new ();
2881 g_ptr_array_add (*res, ic);
2882 mono_class_init (ic);
2883 if (mono_class_has_failure (ic)) {
2884 mono_error_set_type_load_class (error, ic, "Error Loading class");
2888 collect_implemented_interfaces_aux (ic, res, error);
2889 return_if_nok (error);
2894 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2896 GPtrArray *res = NULL;
2898 collect_implemented_interfaces_aux (klass, &res, error);
2899 if (!mono_error_ok (error)) {
2901 g_ptr_array_free (res, TRUE);
2908 compare_interface_ids (const void *p_key, const void *p_element) {
2909 const MonoClass *key = (const MonoClass *)p_key;
2910 const MonoClass *element = *(const MonoClass **)p_element;
2912 return (key->interface_id - element->interface_id);
2915 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2917 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2918 MonoClass **result = (MonoClass **)mono_binary_search (
2920 klass->interfaces_packed,
2921 klass->interface_offsets_count,
2922 sizeof (MonoClass *),
2923 compare_interface_ids);
2925 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2932 * mono_class_interface_offset_with_variance:
2934 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2935 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2937 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2939 * FIXME figure out MS disambiguation rules and fix this function.
2942 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2943 int i = mono_class_interface_offset (klass, itf);
2944 *non_exact_match = FALSE;
2948 if (!mono_class_has_variant_generic_params (itf))
2951 for (i = 0; i < klass->interface_offsets_count; i++) {
2952 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2953 *non_exact_match = TRUE;
2954 return klass->interface_offsets_packed [i];
2962 print_implemented_interfaces (MonoClass *klass) {
2965 GPtrArray *ifaces = NULL;
2967 int ancestor_level = 0;
2969 name = mono_type_get_full_name (klass);
2970 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2973 for (i = 0; i < klass->interface_offsets_count; i++)
2974 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2975 klass->interfaces_packed [i]->interface_id,
2976 klass->interface_offsets_packed [i],
2977 klass->interfaces_packed [i]->method.count,
2978 klass->interfaces_packed [i]->name_space,
2979 klass->interfaces_packed [i]->name );
2980 printf ("Interface flags: ");
2981 for (i = 0; i <= klass->max_interface_id; i++)
2982 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2983 printf ("(%d,T)", i);
2985 printf ("(%d,F)", i);
2987 printf ("Dump interface flags:");
2988 #ifdef COMPRESSED_INTERFACE_BITMAP
2990 const uint8_t* p = klass->interface_bitmap;
2991 i = klass->max_interface_id;
2993 printf (" %d x 00 %02X", p [0], p [1]);
2999 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
3000 printf (" %02X", klass->interface_bitmap [i]);
3003 while (klass != NULL) {
3004 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
3005 ifaces = mono_class_get_implemented_interfaces (klass, &error);
3006 if (!mono_error_ok (&error)) {
3007 printf (" Type failed due to %s\n", mono_error_get_message (&error));
3008 mono_error_cleanup (&error);
3009 } else if (ifaces) {
3010 for (i = 0; i < ifaces->len; i++) {
3011 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3012 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
3013 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3015 mono_class_interface_offset (klass, ic),
3020 g_ptr_array_free (ifaces, TRUE);
3023 klass = klass->parent;
3028 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
3031 args [0] = &arg0->byval_arg;
3033 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
3037 array_class_get_if_rank (MonoClass *klass, guint rank)
3039 return rank ? mono_array_class_get (klass, rank) : klass;
3043 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
3045 valuetype_types [0] = eclass;
3046 if (eclass == mono_defaults.int16_class)
3047 valuetype_types [1] = mono_defaults.uint16_class;
3048 else if (eclass == mono_defaults.uint16_class)
3049 valuetype_types [1] = mono_defaults.int16_class;
3050 else if (eclass == mono_defaults.int32_class)
3051 valuetype_types [1] = mono_defaults.uint32_class;
3052 else if (eclass == mono_defaults.uint32_class)
3053 valuetype_types [1] = mono_defaults.int32_class;
3054 else if (eclass == mono_defaults.int64_class)
3055 valuetype_types [1] = mono_defaults.uint64_class;
3056 else if (eclass == mono_defaults.uint64_class)
3057 valuetype_types [1] = mono_defaults.int64_class;
3058 else if (eclass == mono_defaults.byte_class)
3059 valuetype_types [1] = mono_defaults.sbyte_class;
3060 else if (eclass == mono_defaults.sbyte_class)
3061 valuetype_types [1] = mono_defaults.byte_class;
3062 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
3063 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
3066 /* this won't be needed once bug #325495 is completely fixed
3067 * though we'll need something similar to know which interfaces to allow
3068 * in arrays when they'll be lazyly created
3070 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
3071 * MS returns diferrent types based on which instance is called. For example:
3072 * object obj = new byte[10][];
3073 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
3074 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
3077 * Fixing this should kill quite some code, save some bits and improve compatibility.
3080 get_implicit_generic_array_interfaces (MonoClass *klass, int *num, int *is_enumerator)
3082 MonoClass *eclass = klass->element_class;
3083 static MonoClass* generic_icollection_class = NULL;
3084 static MonoClass* generic_ienumerable_class = NULL;
3085 static MonoClass* generic_ienumerator_class = NULL;
3086 static MonoClass* generic_ireadonlylist_class = NULL;
3087 static MonoClass* generic_ireadonlycollection_class = NULL;
3088 MonoClass *valuetype_types[2] = { NULL, NULL };
3089 MonoClass **interfaces = NULL;
3090 int i, nifaces, interface_count, real_count, original_rank;
3092 gboolean internal_enumerator;
3093 gboolean eclass_is_valuetype;
3095 if (!mono_defaults.generic_ilist_class) {
3099 internal_enumerator = FALSE;
3100 eclass_is_valuetype = FALSE;
3101 original_rank = eclass->rank;
3102 if (klass->byval_arg.type != MONO_TYPE_SZARRAY) {
3103 if (klass->generic_class && klass->nested_in == mono_defaults.array_class && strcmp (klass->name, "InternalEnumerator`1") == 0) {
3105 * For a Enumerator<T[]> we need to get the list of interfaces for T.
3107 eclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
3108 original_rank = eclass->rank;
3110 eclass = eclass->element_class;
3111 internal_enumerator = TRUE;
3112 *is_enumerator = TRUE;
3120 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
3121 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
3123 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
3125 if (!generic_icollection_class) {
3126 generic_icollection_class = mono_class_load_from_name (mono_defaults.corlib,
3127 "System.Collections.Generic", "ICollection`1");
3128 generic_ienumerable_class = mono_class_load_from_name (mono_defaults.corlib,
3129 "System.Collections.Generic", "IEnumerable`1");
3130 generic_ienumerator_class = mono_class_load_from_name (mono_defaults.corlib,
3131 "System.Collections.Generic", "IEnumerator`1");
3132 generic_ireadonlylist_class = mono_class_load_from_name (mono_defaults.corlib,
3133 "System.Collections.Generic", "IReadOnlyList`1");
3134 generic_ireadonlycollection_class = mono_class_load_from_name (mono_defaults.corlib,
3135 "System.Collections.Generic", "IReadOnlyCollection`1");
3138 mono_class_init (eclass);
3141 * Arrays in 2.0 need to implement a number of generic interfaces
3142 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
3143 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
3144 * We collect the types needed to build the
3145 * instantiations in interfaces at intervals of 3/5, because 3/5 are
3146 * the generic interfaces needed to implement.
3148 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
3149 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
3151 if (eclass->valuetype) {
3152 nifaces = generic_ireadonlylist_class ? 5 : 3;
3153 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
3155 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
3156 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
3157 if (internal_enumerator) {
3159 if (valuetype_types [1])
3163 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3164 interfaces [0] = valuetype_types [0];
3165 if (valuetype_types [1])
3166 interfaces [nifaces] = valuetype_types [1];
3168 eclass_is_valuetype = TRUE;
3171 int idepth = eclass->idepth;
3172 if (!internal_enumerator)
3174 nifaces = generic_ireadonlylist_class ? 2 : 3;
3176 // FIXME: This doesn't seem to work/required for generic params
3177 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
3178 mono_class_setup_interface_offsets (eclass);
3180 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
3181 /* we add object for interfaces and the supertypes for the other
3182 * types. The last of the supertypes is the element class itself which we
3183 * already created the explicit interfaces for (so we include it for IEnumerator
3184 * and exclude it for arrays).
3186 if (MONO_CLASS_IS_INTERFACE (eclass))
3189 interface_count += idepth;
3190 if (eclass->rank && eclass->element_class->valuetype) {
3191 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3192 if (valuetype_types [1])
3195 /* IList, ICollection, IEnumerable, IReadOnlyList */
3196 interface_count *= nifaces;
3197 real_count = interface_count;
3198 if (internal_enumerator) {
3199 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3200 if (valuetype_types [1])
3203 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3204 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3205 interfaces [0] = mono_defaults.object_class;
3209 for (i = 0; i < idepth; i++) {
3210 mono_class_init (eclass->supertypes [i]);
3211 interfaces [j] = eclass->supertypes [i];
3215 if (all_interfaces) {
3216 for (i = 0; i < eclass->interface_offsets_count; i++) {
3217 interfaces [j] = eclass->interfaces_packed [i];
3221 for (i = 0; i < eclass->interface_count; i++) {
3222 interfaces [j] = eclass->interfaces [i];
3226 if (valuetype_types [1]) {
3227 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3232 /* instantiate the generic interfaces */
3233 for (i = 0; i < interface_count; i += nifaces) {
3234 MonoClass *iface = interfaces [i];
3236 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3237 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3239 if (eclass->valuetype) {
3240 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3241 if (generic_ireadonlylist_class) {
3242 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3243 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3246 if (!generic_ireadonlylist_class)
3247 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3250 if (internal_enumerator) {
3252 /* instantiate IEnumerator<iface> */
3253 for (i = 0; i < interface_count; i++) {
3254 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3256 j = interface_count;
3257 if (!eclass_is_valuetype) {
3258 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3259 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3262 for (i = 0; i < eclass->idepth; i++) {
3263 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3267 for (i = 0; i < eclass->interface_offsets_count; i++) {
3268 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3272 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3274 if (valuetype_types [1])
3275 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3279 char *type_name = mono_type_get_name_full (&klass->byval_arg, 0);
3280 for (i = 0; i < real_count; ++i) {
3281 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3282 g_print ("%s implements %s\n", type_name, name);
3293 find_array_interface (MonoClass *klass, const char *name)
3296 for (i = 0; i < klass->interface_count; ++i) {
3297 if (strcmp (klass->interfaces [i]->name, name) == 0)
3304 * Return the number of virtual methods.
3305 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3306 * Return -1 on failure.
3307 * FIXME It would be nice if this information could be cached somewhere.
3310 count_virtual_methods (MonoClass *klass)
3314 klass = mono_class_get_generic_type_definition (klass); /*We can find this information by looking at the GTD*/
3316 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
3317 mono_class_setup_methods (klass);
3318 if (mono_class_has_failure (klass))
3321 for (i = 0; i < klass->method.count; ++i) {
3322 flags = klass->methods [i]->flags;
3323 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3327 for (i = 0; i < klass->method.count; ++i) {
3328 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
3330 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3338 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3346 m = (l + num_ifaces) / 2;
3347 if (interfaces_full [m] == ic)
3349 if (l == num_ifaces)
3351 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3360 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3362 int i = find_interface (num_ifaces, interfaces_full, ic);
3364 return interface_offsets_full [i];
3369 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3371 int i = find_interface (num_ifaces, interfaces_full, ic);
3375 interface_offsets_full [i] = offset;
3378 for (i = 0; i < num_ifaces; ++i) {
3379 if (interfaces_full [i]) {
3381 if (interfaces_full [i]->interface_id < ic->interface_id)
3384 while (end < num_ifaces && interfaces_full [end]) end++;
3385 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3386 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3388 interfaces_full [i] = ic;
3389 interface_offsets_full [i] = offset;
3395 #ifdef COMPRESSED_INTERFACE_BITMAP
3398 * Compressed interface bitmap design.
3400 * Interface bitmaps take a large amount of memory, because their size is
3401 * linear with the maximum interface id assigned in the process (each interface
3402 * is assigned a unique id as it is loaded). The number of interface classes
3403 * is high because of the many implicit interfaces implemented by arrays (we'll
3404 * need to lazy-load them in the future).
3405 * Most classes implement a very small number of interfaces, so the bitmap is
3406 * sparse. This bitmap needs to be checked by interface casts, so access to the
3407 * needed bit must be fast and doable with few jit instructions.
3409 * The current compression format is as follows:
3410 * *) it is a sequence of one or more two-byte elements
3411 * *) the first byte in the element is the count of empty bitmap bytes
3412 * at the current bitmap position
3413 * *) the second byte in the element is an actual bitmap byte at the current
3416 * As an example, the following compressed bitmap bytes:
3417 * 0x07 0x01 0x00 0x7
3418 * correspond to the following bitmap:
3419 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3421 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3422 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3423 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3427 * mono_compress_bitmap:
3428 * @dest: destination buffer
3429 * @bitmap: bitmap buffer
3430 * @size: size of @bitmap in bytes
3432 * This is a mono internal function.
3433 * The @bitmap data is compressed into a format that is small but
3434 * still searchable in few instructions by the JIT and runtime.
3435 * The compressed data is stored in the buffer pointed to by the
3436 * @dest array. Passing a #NULL value for @dest allows to just compute
3437 * the size of the buffer.
3438 * This compression algorithm assumes the bits set in the bitmap are
3439 * few and far between, like in interface bitmaps.
3440 * Returns: The size of the compressed bitmap in bytes.
3443 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3447 const uint8_t *end = bitmap + size;
3448 while (bitmap < end) {
3449 if (*bitmap || numz == 255) {
3473 * mono_class_interface_match:
3474 * @bitmap: a compressed bitmap buffer
3475 * @id: the index to check in the bitmap
3477 * This is a mono internal function.
3478 * Checks if a bit is set in a compressed interface bitmap. @id must
3479 * be already checked for being smaller than the maximum id encoded in the
3482 * Returns: A non-zero value if bit @id is set in the bitmap @bitmap,
3486 mono_class_interface_match (const uint8_t *bitmap, int id)
3489 id -= bitmap [0] * 8;
3493 return bitmap [1] & (1 << id);
3502 * LOCKING: this is supposed to be called with the loader lock held.
3503 * Return -1 on failure and set exception_type
3506 setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite)
3510 int i, j, max_iid, num_ifaces;
3511 MonoClass **interfaces_full = NULL;
3512 int *interface_offsets_full = NULL;
3514 GPtrArray **ifaces_array = NULL;
3515 int interface_offsets_count;
3516 MonoClass **array_interfaces = NULL;
3517 int num_array_interfaces;
3518 int is_enumerator = FALSE;
3520 mono_class_setup_supertypes (klass);
3522 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3523 * implicit interfaces have the property that they are assigned the same slot in the
3524 * vtables for compatible interfaces
3526 array_interfaces = get_implicit_generic_array_interfaces (klass, &num_array_interfaces, &is_enumerator);
3528 /* compute maximum number of slots and maximum interface id */
3530 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3531 ifaces_array = g_new0 (GPtrArray *, klass->idepth);
3532 for (j = 0; j < klass->idepth; j++) {
3533 k = klass->supertypes [j];
3534 num_ifaces += k->interface_count;
3535 for (i = 0; i < k->interface_count; i++) {
3536 ic = k->interfaces [i];
3539 mono_class_init (ic);
3541 if (max_iid < ic->interface_id)
3542 max_iid = ic->interface_id;
3544 ifaces = mono_class_get_implemented_interfaces (k, &error);
3545 if (!mono_error_ok (&error)) {
3546 char *name = mono_type_get_full_name (k);
3547 mono_class_set_type_load_failure (klass, "Error getting the interfaces of %s due to %s", name, mono_error_get_message (&error));
3549 mono_error_cleanup (&error);
3554 num_ifaces += ifaces->len;
3555 for (i = 0; i < ifaces->len; ++i) {
3556 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3557 if (max_iid < ic->interface_id)
3558 max_iid = ic->interface_id;
3560 ifaces_array [j] = ifaces;
3564 for (i = 0; i < num_array_interfaces; ++i) {
3565 ic = array_interfaces [i];
3566 mono_class_init (ic);
3567 if (max_iid < ic->interface_id)
3568 max_iid = ic->interface_id;
3571 if (MONO_CLASS_IS_INTERFACE (klass)) {
3573 if (max_iid < klass->interface_id)
3574 max_iid = klass->interface_id;
3576 klass->max_interface_id = max_iid;
3577 /* compute vtable offset for interfaces */
3578 interfaces_full = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3579 interface_offsets_full = (int *)g_malloc (sizeof (int) * num_ifaces);
3581 for (i = 0; i < num_ifaces; i++) {
3582 interface_offsets_full [i] = -1;
3585 /* skip the current class */
3586 for (j = 0; j < klass->idepth - 1; j++) {
3587 k = klass->supertypes [j];
3588 ifaces = ifaces_array [j];
3591 for (i = 0; i < ifaces->len; ++i) {
3593 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3595 /*Force the sharing of interface offsets between parent and subtypes.*/
3596 io = mono_class_interface_offset (k, ic);
3598 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3603 g_assert (klass == klass->supertypes [klass->idepth - 1]);
3604 ifaces = ifaces_array [klass->idepth - 1];
3606 for (i = 0; i < ifaces->len; ++i) {
3608 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3609 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3611 count = count_virtual_methods (ic);
3613 char *name = mono_type_get_full_name (ic);
3614 mono_class_set_type_load_failure (klass, "Error calculating interface offset of %s", name);
3623 if (MONO_CLASS_IS_INTERFACE (klass))
3624 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, klass, cur_slot, TRUE);
3626 if (num_array_interfaces) {
3627 if (is_enumerator) {
3628 int ienumerator_idx = find_array_interface (klass, "IEnumerator`1");
3629 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ienumerator_idx]);
3630 g_assert (ienumerator_offset >= 0);
3631 for (i = 0; i < num_array_interfaces; ++i) {
3632 ic = array_interfaces [i];
3633 if (strcmp (ic->name, "IEnumerator`1") == 0)
3634 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3636 g_assert_not_reached ();
3637 /*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);*/
3640 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3641 int ilist_iface_idx = find_array_interface (klass, "IList`1");
3642 MonoClass* ilist_class = klass->interfaces [ilist_iface_idx];
3643 int ireadonlylist_iface_idx = find_array_interface (klass, "IReadOnlyList`1");
3644 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? klass->interfaces [ireadonlylist_iface_idx] : NULL;
3645 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3646 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3647 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3648 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ilist_iface_idx]);
3649 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3650 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3651 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ireadonlylist_iface_idx]) : -1;
3652 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3653 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3654 for (i = 0; i < num_array_interfaces; ++i) {
3656 ic = array_interfaces [i];
3657 if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
3658 offset = ilist_offset;
3659 else if (strcmp (ic->name, "ICollection`1") == 0)
3660 offset = icollection_offset;
3661 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3662 offset = ienumerable_offset;
3663 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3664 offset = ireadonlylist_offset;
3665 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3666 offset = ireadonlycollection_offset;
3668 g_assert_not_reached ();
3669 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3670 /*g_print ("type %s has %s offset at %d (%s)\n", klass->name, ic->name, offset, klass->interfaces [0]->name);*/
3675 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3676 if (interface_offsets_full [i] != -1) {
3677 interface_offsets_count ++;
3682 * We might get called multiple times:
3683 * - mono_class_init ()
3684 * - mono_class_setup_vtable ().
3685 * - mono_class_setup_interface_offsets ().
3686 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3687 * means we have to overwrite those when called from other places (#4440).
3689 if (klass->interfaces_packed) {
3691 g_assert (klass->interface_offsets_count == interface_offsets_count);
3695 klass->interface_offsets_count = interface_offsets_count;
3696 klass->interfaces_packed = (MonoClass **)mono_class_alloc (klass, sizeof (MonoClass*) * interface_offsets_count);
3697 klass->interface_offsets_packed = (guint16 *)mono_class_alloc (klass, sizeof (guint16) * interface_offsets_count);
3698 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3699 #ifdef COMPRESSED_INTERFACE_BITMAP
3700 bitmap = g_malloc0 (bsize);
3702 bitmap = (uint8_t *)mono_class_alloc0 (klass, bsize);
3704 for (i = 0; i < interface_offsets_count; i++) {
3705 int id = interfaces_full [i]->interface_id;
3706 bitmap [id >> 3] |= (1 << (id & 7));
3707 klass->interfaces_packed [i] = interfaces_full [i];
3708 klass->interface_offsets_packed [i] = interface_offsets_full [i];
3709 /*if (num_array_interfaces)
3710 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]);*/
3712 #ifdef COMPRESSED_INTERFACE_BITMAP
3713 i = mono_compress_bitmap (NULL, bitmap, bsize);
3714 klass->interface_bitmap = mono_class_alloc0 (klass, i);
3715 mono_compress_bitmap (klass->interface_bitmap, bitmap, bsize);
3718 klass->interface_bitmap = bitmap;
3723 g_free (interfaces_full);
3724 g_free (interface_offsets_full);
3725 g_free (array_interfaces);
3726 for (i = 0; i < klass->idepth; i++) {
3727 ifaces = ifaces_array [i];
3729 g_ptr_array_free (ifaces, TRUE);
3731 g_free (ifaces_array);
3733 //printf ("JUST DONE: ");
3734 //print_implemented_interfaces (klass);
3740 * Setup interface offsets for interfaces.
3742 * - klass->max_interface_id
3743 * - klass->interface_offsets_count
3744 * - klass->interfaces_packed
3745 * - klass->interface_offsets_packed
3746 * - klass->interface_bitmap
3748 * This function can fail @class.
3751 mono_class_setup_interface_offsets (MonoClass *klass)
3753 mono_loader_lock ();
3755 setup_interface_offsets (klass, 0, FALSE);
3757 mono_loader_unlock ();
3760 /*Checks if @klass has @parent as one of it's parents type gtd
3764 * Bar<T> : Foo<Bar<Bar<T>>>
3768 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3770 klass = mono_class_get_generic_type_definition (klass);
3771 parent = mono_class_get_generic_type_definition (parent);
3772 mono_class_setup_supertypes (klass);
3773 mono_class_setup_supertypes (parent);
3775 return klass->idepth >= parent->idepth &&
3776 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3780 mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup)
3782 MonoGenericInst *ginst;
3784 if (!klass->generic_class) {
3785 mono_class_setup_vtable_full (klass, in_setup);
3786 return !mono_class_has_failure (klass);
3789 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup);
3790 if (mono_class_has_failure (klass->generic_class->container_class)) {
3791 mono_class_set_type_load_failure (klass, "Failed to load generic definition vtable");
3795 ginst = klass->generic_class->context.class_inst;
3796 for (i = 0; i < ginst->type_argc; ++i) {
3798 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3800 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3801 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3802 if (mono_class_has_gtd_parent (klass, arg) || mono_class_has_gtd_parent (arg, klass))
3804 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3805 mono_class_set_type_load_failure (klass, "Failed to load generic parameter %d", i);
3813 * mono_class_setup_vtable:
3815 * Creates the generic vtable of CLASS.
3816 * Initializes the following fields in MonoClass:
3819 * Plus all the fields initialized by setup_interface_offsets ().
3820 * If there is an error during vtable construction, klass->exception_type is set.
3822 * LOCKING: Acquires the loader lock.
3825 mono_class_setup_vtable (MonoClass *klass)
3827 mono_class_setup_vtable_full (klass, NULL);
3831 mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
3834 MonoMethod **overrides;
3835 MonoGenericContext *context;
3843 if (MONO_CLASS_IS_INTERFACE (klass)) {
3844 /* This sets method->slot for all methods if this is an interface */
3845 mono_class_setup_methods (klass);
3849 if (mono_class_has_failure (klass))
3852 if (g_list_find (in_setup, klass))
3855 mono_loader_lock ();
3857 if (klass->vtable) {
3858 mono_loader_unlock ();
3862 mono_stats.generic_vtable_count ++;
3863 in_setup = g_list_prepend (in_setup, klass);
3865 if (klass->generic_class) {
3866 if (!mono_class_check_vtable_constraints (klass, in_setup)) {
3867 mono_loader_unlock ();
3868 g_list_remove (in_setup, klass);
3872 context = mono_class_get_context (klass);
3873 type_token = klass->generic_class->container_class->type_token;
3875 context = (MonoGenericContext *) klass->generic_container;
3876 type_token = klass->type_token;
3879 if (image_is_dynamic (klass->image)) {
3880 /* Generic instances can have zero method overrides without causing any harm.
3881 * This is true since we don't do layout all over again for them, we simply inflate
3882 * the layout of the parent.
3884 mono_reflection_get_dynamic_overrides (klass, &overrides, &onum, &error);
3885 if (!is_ok (&error)) {
3886 mono_loader_unlock ();
3887 g_list_remove (in_setup, klass);
3888 mono_class_set_type_load_failure (klass, "Could not load list of method overrides due to %s", mono_error_get_message (&error));
3889 mono_error_cleanup (&error);
3893 /* The following call fails if there are missing methods in the type */
3894 /* FIXME it's probably a good idea to avoid this for generic instances. */
3895 ok = mono_class_get_overrides_full (klass->image, type_token, &overrides, &onum, context);
3899 mono_class_setup_vtable_general (klass, overrides, onum, in_setup);
3901 mono_class_set_type_load_failure (klass, "Could not load list of method overrides");
3905 mono_loader_unlock ();
3906 g_list_remove (in_setup, klass);
3911 #define DEBUG_INTERFACE_VTABLE_CODE 0
3912 #define TRACE_INTERFACE_VTABLE_CODE 0
3913 #define VERIFY_INTERFACE_VTABLE_CODE 0
3914 #define VTABLE_SELECTOR (1)
3916 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3917 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3918 if (!(VTABLE_SELECTOR)) break; \
3922 #define DEBUG_INTERFACE_VTABLE(stmt)
3925 #if TRACE_INTERFACE_VTABLE_CODE
3926 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3927 if (!(VTABLE_SELECTOR)) break; \
3931 #define TRACE_INTERFACE_VTABLE(stmt)
3934 #if VERIFY_INTERFACE_VTABLE_CODE
3935 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3936 if (!(VTABLE_SELECTOR)) break; \
3940 #define VERIFY_INTERFACE_VTABLE(stmt)
3944 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3946 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3950 GString *res = g_string_new ("");
3952 g_string_append_c (res, '(');
3953 for (i = 0; i < sig->param_count; ++i) {
3955 g_string_append_c (res, ',');
3956 mono_type_get_desc (res, sig->params [i], include_namespace);
3958 g_string_append (res, ")=>");
3959 if (sig->ret != NULL) {
3960 mono_type_get_desc (res, sig->ret, include_namespace);
3962 g_string_append (res, "NULL");
3965 g_string_free (res, FALSE);
3969 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3970 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3971 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3972 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3980 is_wcf_hack_disabled (void)
3982 static gboolean disabled;
3983 static gboolean inited = FALSE;
3985 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3992 check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
3994 MonoMethodSignature *cmsig, *imsig;
3995 if (strcmp (im->name, cm->name) == 0) {
3996 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3997 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
4000 if (! slot_is_empty) {
4001 if (require_newslot) {
4002 if (! interface_is_explicitly_implemented_by_class) {
4003 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
4006 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4007 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
4011 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
4014 cmsig = mono_method_signature (cm);
4015 imsig = mono_method_signature (im);
4016 if (!cmsig || !imsig) {
4017 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
4021 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4022 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
4023 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4024 TRACE_INTERFACE_VTABLE (printf ("]"));
4027 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
4028 if (mono_security_core_clr_enabled ())
4029 mono_security_core_clr_check_override (klass, cm, im);
4031 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
4032 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4033 char *body_name = mono_method_full_name (cm, TRUE);
4034 char *decl_name = mono_method_full_name (im, TRUE);
4035 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4043 MonoClass *ic = im->klass;
4044 const char *ic_name_space = ic->name_space;
4045 const char *ic_name = ic->name;
4048 if (! require_newslot) {
4049 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
4052 if (cm->klass->rank == 0) {
4053 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
4056 cmsig = mono_method_signature (cm);
4057 imsig = mono_method_signature (im);
4058 if (!cmsig || !imsig) {
4059 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
4063 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4064 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
4065 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4066 TRACE_INTERFACE_VTABLE (printf ("]"));
4069 if (mono_class_get_image (ic) != mono_defaults.corlib) {
4070 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
4073 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
4074 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
4077 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))) {
4078 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
4082 subname = strstr (cm->name, ic_name_space);
4083 if (subname != cm->name) {
4084 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
4087 subname += strlen (ic_name_space);
4088 if (subname [0] != '.') {
4089 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
4093 if (strstr (subname, ic_name) != subname) {
4094 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
4097 subname += strlen (ic_name);
4098 if (subname [0] != '.') {
4099 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
4103 if (strcmp (subname, im->name) != 0) {
4104 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
4108 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
4109 if (mono_security_core_clr_enabled ())
4110 mono_security_core_clr_check_override (klass, cm, im);
4112 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
4113 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4114 char *body_name = mono_method_full_name (cm, TRUE);
4115 char *decl_name = mono_method_full_name (im, TRUE);
4116 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4126 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
4128 foreach_override (gpointer key, gpointer value, gpointer user_data) {
4129 MonoMethod *method = key;
4130 MonoMethod *override = value;
4131 MonoClass *method_class = mono_method_get_class (method);
4132 MonoClass *override_class = mono_method_get_class (override);
4134 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
4135 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
4136 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
4139 print_overrides (GHashTable *override_map, const char *message) {
4141 printf ("Override map \"%s\" START:\n", message);
4142 g_hash_table_foreach (override_map, foreach_override, NULL);
4143 printf ("Override map \"%s\" END.\n", message);
4145 printf ("Override map \"%s\" EMPTY.\n", message);
4149 print_vtable_full (MonoClass *klass, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
4150 char *full_name = mono_type_full_name (&klass->byval_arg);
4154 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
4156 if (print_interfaces) {
4157 print_implemented_interfaces (klass);
4158 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
4161 if (klass->parent) {
4162 parent_size = klass->parent->vtable_size;
4166 for (i = 0; i < size; ++i) {
4167 MonoMethod *cm = vtable [i];
4168 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
4169 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
4171 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
4179 #if VERIFY_INTERFACE_VTABLE_CODE
4181 mono_method_try_get_vtable_index (MonoMethod *method)
4183 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4184 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4185 if (imethod->declaring->is_generic)
4186 return imethod->declaring->slot;
4188 return method->slot;
4192 mono_class_verify_vtable (MonoClass *klass)
4195 char *full_name = mono_type_full_name (&klass->byval_arg);
4197 printf ("*** Verifying VTable of class '%s' \n", full_name);
4201 if (!klass->methods)
4204 for (i = 0; i < klass->method.count; ++i) {
4205 MonoMethod *cm = klass->methods [i];
4208 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4212 full_name = mono_method_full_name (cm, TRUE);
4214 slot = mono_method_try_get_vtable_index (cm);
4216 if (slot >= klass->vtable_size) {
4217 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, klass->vtable_size);
4221 if (slot >= 0 && klass->vtable [slot] != cm && (klass->vtable [slot])) {
4222 char *other_name = klass->vtable [slot] ? mono_method_full_name (klass->vtable [slot], TRUE) : g_strdup ("[null value]");
4223 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4224 g_free (other_name);
4227 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4234 print_unimplemented_interface_method_info (MonoClass *klass, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4236 char *method_signature;
4239 for (index = 0; index < onum; ++index) {
4240 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4241 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4243 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4244 type_name = mono_type_full_name (&klass->byval_arg);
4245 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4246 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4247 g_free (method_signature);
4249 mono_class_setup_methods (klass);
4250 if (mono_class_has_failure (klass)) {
4251 char *name = mono_type_get_full_name (klass);
4252 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4256 for (index = 0; index < klass->method.count; ++index) {
4257 MonoMethod *cm = klass->methods [index];
4258 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4260 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4261 g_free (method_signature);
4266 mono_method_get_method_definition (MonoMethod *method)
4268 while (method->is_inflated)
4269 method = ((MonoMethodInflated*)method)->declaring;
4274 verify_class_overrides (MonoClass *klass, MonoMethod **overrides, int onum)
4278 for (i = 0; i < onum; ++i) {
4279 MonoMethod *decl = overrides [i * 2];
4280 MonoMethod *body = overrides [i * 2 + 1];
4282 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (klass)) {
4283 mono_class_set_type_load_failure (klass, "Method belongs to a different class than the declared one");
4287 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4288 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4289 mono_class_set_type_load_failure (klass, "Method must not be static to override a base type");
4291 mono_class_set_type_load_failure (klass, "Method must be virtual to override a base type");
4295 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4296 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4297 mono_class_set_type_load_failure (klass, "Cannot override a static method in a base type");
4299 mono_class_set_type_load_failure (klass, "Cannot override a non virtual method in a base type");
4303 if (!mono_class_is_assignable_from_slow (decl->klass, klass)) {
4304 mono_class_set_type_load_failure (klass, "Method overrides a class or interface that is not extended or implemented by this type");
4308 body = mono_method_get_method_definition (body);
4309 decl = mono_method_get_method_definition (decl);
4311 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4312 char *body_name = mono_method_full_name (body, TRUE);
4313 char *decl_name = mono_method_full_name (decl, TRUE);
4314 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4324 mono_class_need_stelemref_method (MonoClass *klass)
4326 return klass->rank == 1 && MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg);
4330 * LOCKING: this is supposed to be called with the loader lock held.
4333 mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int onum, GList *in_setup)
4337 MonoMethod **vtable;
4338 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4339 GPtrArray *ifaces = NULL;
4340 GHashTable *override_map = NULL;
4342 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4343 int first_non_interface_slot;
4345 GSList *virt_methods = NULL, *l;
4346 int stelemref_slot = 0;
4351 if (overrides && !verify_class_overrides (klass, overrides, onum))
4354 ifaces = mono_class_get_implemented_interfaces (klass, &error);
4355 if (!mono_error_ok (&error)) {
4356 char *name = mono_type_get_full_name (klass);
4357 mono_class_set_type_load_failure (klass, "Could not resolve %s interfaces due to %s", name, mono_error_get_message (&error));
4359 mono_error_cleanup (&error);
4361 } else if (ifaces) {
4362 for (i = 0; i < ifaces->len; i++) {
4363 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
4364 max_vtsize += ic->method.count;
4366 g_ptr_array_free (ifaces, TRUE);
4370 if (klass->parent) {
4371 mono_class_init (klass->parent);
4372 mono_class_setup_vtable_full (klass->parent, in_setup);
4374 if (mono_class_has_failure (klass->parent)) {
4375 char *name = mono_type_get_full_name (klass->parent);
4376 mono_class_set_type_load_failure (klass, "Parent %s failed to load", name);
4381 max_vtsize += klass->parent->vtable_size;
4382 cur_slot = klass->parent->vtable_size;
4385 max_vtsize += klass->method.count;
4387 /*Array have a slot for stelemref*/
4388 if (mono_class_need_stelemref_method (klass)) {
4389 stelemref_slot = cur_slot;
4394 vtable = (MonoMethod **)alloca (sizeof (gpointer) * max_vtsize);
4395 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4397 /* printf ("METAINIT %s.%s\n", klass->name_space, klass->name); */
4399 cur_slot = setup_interface_offsets (klass, cur_slot, TRUE);
4400 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4403 max_iid = klass->max_interface_id;
4404 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4406 /* Optimized version for generic instances */
4407 if (klass->generic_class) {
4409 MonoClass *gklass = klass->generic_class->container_class;
4412 mono_class_setup_vtable_full (gklass, in_setup);
4413 if (mono_class_has_failure (gklass)) {
4414 mono_class_set_type_load_failure (klass, "");
4418 tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * gklass->vtable_size);
4419 klass->vtable_size = gklass->vtable_size;
4420 for (i = 0; i < gklass->vtable_size; ++i)
4421 if (gklass->vtable [i]) {
4422 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], klass, mono_class_get_context (klass), &error);
4423 if (!mono_error_ok (&error)) {
4424 mono_class_set_type_load_failure (klass, "Could not inflate method due to %s", mono_error_get_message (&error));
4425 mono_error_cleanup (&error);
4429 tmp [i]->slot = gklass->vtable [i]->slot;
4431 mono_memory_barrier ();
4432 klass->vtable = tmp;
4434 /* Have to set method->slot for abstract virtual methods */
4435 if (klass->methods && gklass->methods) {
4436 for (i = 0; i < klass->method.count; ++i)
4437 if (klass->methods [i]->slot == -1)
4438 klass->methods [i]->slot = gklass->methods [i]->slot;
4444 if (klass->parent && klass->parent->vtable_size) {
4445 MonoClass *parent = klass->parent;
4448 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4450 // Also inherit parent interface vtables, just as a starting point.
4451 // This is needed otherwise bug-77127.exe fails when the property methods
4452 // have different names in the iterface and the class, because for child
4453 // classes the ".override" information is not used anymore.
4454 for (i = 0; i < parent->interface_offsets_count; i++) {
4455 MonoClass *parent_interface = parent->interfaces_packed [i];
4456 int interface_offset = mono_class_interface_offset (klass, parent_interface);
4457 /*FIXME this is now dead code as this condition will never hold true.
4458 Since interface offsets are inherited then the offset of an interface implemented
4459 by a parent will never be the out of it's vtable boundary.
4461 if (interface_offset >= parent->vtable_size) {
4462 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4465 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4466 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4467 for (j = 0; j < parent_interface->method.count && !mono_class_has_failure (klass); j++) {
4468 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4469 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4470 parent_interface_offset + j, parent_interface_offset, j,
4471 interface_offset + j, interface_offset, j));
4478 /*Array have a slot for stelemref*/
4479 if (mono_class_need_stelemref_method (klass)) {
4480 MonoMethod *method = mono_marshal_get_virtual_stelemref (klass);
4482 method->slot = stelemref_slot;
4484 g_assert (method->slot == stelemref_slot);
4486 vtable [stelemref_slot] = method;
4489 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4490 /* override interface methods */
4491 for (i = 0; i < onum; i++) {
4492 MonoMethod *decl = overrides [i*2];
4493 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4495 dslot = mono_method_get_vtable_slot (decl);
4497 mono_class_set_type_load_failure (klass, "");
4501 dslot += mono_class_interface_offset (klass, decl->klass);
4502 vtable [dslot] = overrides [i*2 + 1];
4503 vtable [dslot]->slot = dslot;
4505 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4507 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4509 if (mono_security_core_clr_enabled ())
4510 mono_security_core_clr_check_override (klass, vtable [dslot], decl);
4513 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4514 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4517 * Create a list of virtual methods to avoid calling
4518 * mono_class_get_virtual_methods () which is slow because of the metadata
4522 gpointer iter = NULL;
4525 virt_methods = NULL;
4526 while ((cm = mono_class_get_virtual_methods (klass, &iter))) {
4527 virt_methods = g_slist_prepend (virt_methods, cm);
4529 if (mono_class_has_failure (klass))
4533 // Loop on all implemented interfaces...
4534 for (i = 0; i < klass->interface_offsets_count; i++) {
4535 MonoClass *parent = klass->parent;
4537 gboolean interface_is_explicitly_implemented_by_class;
4540 ic = klass->interfaces_packed [i];
4541 ic_offset = mono_class_interface_offset (klass, ic);
4543 mono_class_setup_methods (ic);
4544 if (mono_class_has_failure (ic))
4547 // Check if this interface is explicitly implemented (instead of just inherited)
4548 if (parent != NULL) {
4549 int implemented_interfaces_index;
4550 interface_is_explicitly_implemented_by_class = FALSE;
4551 for (implemented_interfaces_index = 0; implemented_interfaces_index < klass->interface_count; implemented_interfaces_index++) {
4552 if (ic == klass->interfaces [implemented_interfaces_index]) {
4553 interface_is_explicitly_implemented_by_class = TRUE;
4558 interface_is_explicitly_implemented_by_class = TRUE;
4561 // Loop on all interface methods...
4562 for (im_index = 0; im_index < ic->method.count; im_index++) {
4563 MonoMethod *im = ic->methods [im_index];
4564 int im_slot = ic_offset + im->slot;
4565 MonoMethod *override_im = (override_map != NULL) ? (MonoMethod *)g_hash_table_lookup (override_map, im) : NULL;
4567 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4570 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4572 // If there is an explicit implementation, just use it right away,
4573 // otherwise look for a matching method
4574 if (override_im == NULL) {
4578 // First look for a suitable method among the class methods
4579 for (l = virt_methods; l; l = l->next) {
4580 cm = (MonoMethod *)l->data;
4581 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)));
4582 if (check_interface_method_override (klass, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
4583 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4584 vtable [im_slot] = cm;
4585 /* Why do we need this? */
4590 TRACE_INTERFACE_VTABLE (printf ("\n"));
4591 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4595 // If the slot is still empty, look in all the inherited virtual methods...
4596 if ((vtable [im_slot] == NULL) && klass->parent != NULL) {
4597 MonoClass *parent = klass->parent;
4598 // Reverse order, so that last added methods are preferred
4599 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4600 MonoMethod *cm = parent->vtable [cm_index];
4602 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));
4603 if ((cm != NULL) && check_interface_method_override (klass, im, cm, FALSE, FALSE, TRUE)) {
4604 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4605 vtable [im_slot] = cm;
4606 /* Why do we need this? */
4612 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4614 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4618 g_assert (vtable [im_slot] == override_im);
4623 // If the class is not abstract, check that all its interface slots are full.
4624 // The check is done here and not directly at the end of the loop above because
4625 // it can happen (for injected generic array interfaces) that the same slot is
4626 // processed multiple times (those interfaces have overlapping slots), and it
4627 // will not always be the first pass the one that fills the slot.
4628 if (! (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4629 for (i = 0; i < klass->interface_offsets_count; i++) {
4633 ic = klass->interfaces_packed [i];
4634 ic_offset = mono_class_interface_offset (klass, ic);
4636 for (im_index = 0; im_index < ic->method.count; im_index++) {
4637 MonoMethod *im = ic->methods [im_index];
4638 int im_slot = ic_offset + im->slot;
4640 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4643 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4644 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4645 if (vtable [im_slot] == NULL) {
4646 print_unimplemented_interface_method_info (klass, ic, im, im_slot, overrides, onum);
4653 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4654 for (l = virt_methods; l; l = l->next) {
4655 cm = (MonoMethod *)l->data;
4657 * If the method is REUSE_SLOT, we must check in the
4658 * base class for a method to override.
4660 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4662 for (k = klass->parent; k ; k = k->parent) {
4667 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4668 MonoMethodSignature *cmsig, *m1sig;
4670 cmsig = mono_method_signature (cm);
4671 m1sig = mono_method_signature (m1);
4673 if (!cmsig || !m1sig) {
4674 mono_class_set_type_load_failure (klass, "");
4678 if (!strcmp(cm->name, m1->name) &&
4679 mono_metadata_signature_equal (cmsig, m1sig)) {
4681 if (mono_security_core_clr_enabled ())
4682 mono_security_core_clr_check_override (klass, cm, m1);
4684 slot = mono_method_get_vtable_slot (m1);
4688 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4689 char *body_name = mono_method_full_name (cm, TRUE);
4690 char *decl_name = mono_method_full_name (m1, TRUE);
4691 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4697 g_assert (cm->slot < max_vtsize);
4699 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4700 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4701 mono_method_full_name (m1, 1), m1,
4702 mono_method_full_name (cm, 1), cm));
4703 g_hash_table_insert (override_map, m1, cm);
4707 if (mono_class_has_failure (k))
4717 /*Non final newslot methods must be given a non-interface vtable slot*/
4718 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4722 cm->slot = cur_slot++;
4724 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4725 vtable [cm->slot] = cm;
4728 /* override non interface methods */
4729 for (i = 0; i < onum; i++) {
4730 MonoMethod *decl = overrides [i*2];
4731 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4732 g_assert (decl->slot != -1);
4733 vtable [decl->slot] = overrides [i*2 + 1];
4734 overrides [i * 2 + 1]->slot = decl->slot;
4736 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4737 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4738 mono_method_full_name (decl, 1), decl,
4739 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4740 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4742 if (mono_security_core_clr_enabled ())
4743 mono_security_core_clr_check_override (klass, vtable [decl->slot], decl);
4748 * If a method occupies more than one place in the vtable, and it is
4749 * overriden, then change the other occurances too.
4754 for (i = 0; i < max_vtsize; ++i)
4756 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4758 cm = (MonoMethod *)g_hash_table_lookup (override_map, vtable [i]);
4763 g_hash_table_destroy (override_map);
4764 override_map = NULL;
4767 g_slist_free (virt_methods);
4768 virt_methods = NULL;
4770 /* Ensure that all vtable slots are filled with concrete instance methods */
4771 if (!(klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4772 for (i = 0; i < cur_slot; ++i) {
4773 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4774 char *type_name = mono_type_get_full_name (klass);
4775 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4776 mono_class_set_type_load_failure (klass, "Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name);
4778 g_free (method_name);
4784 if (klass->generic_class) {
4785 MonoClass *gklass = klass->generic_class->container_class;
4787 mono_class_init (gklass);
4789 klass->vtable_size = MAX (gklass->vtable_size, cur_slot);
4791 /* Check that the vtable_size value computed in mono_class_init () is correct */
4792 if (klass->vtable_size)
4793 g_assert (cur_slot == klass->vtable_size);
4794 klass->vtable_size = cur_slot;
4797 /* Try to share the vtable with our parent. */
4798 if (klass->parent && (klass->parent->vtable_size == klass->vtable_size) && (memcmp (klass->parent->vtable, vtable, sizeof (gpointer) * klass->vtable_size) == 0)) {
4799 mono_memory_barrier ();
4800 klass->vtable = klass->parent->vtable;
4802 MonoMethod **tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * klass->vtable_size);
4803 memcpy (tmp, vtable, sizeof (gpointer) * klass->vtable_size);
4804 mono_memory_barrier ();
4805 klass->vtable = tmp;
4808 DEBUG_INTERFACE_VTABLE (print_vtable_full (klass, klass->vtable, klass->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4809 if (mono_print_vtable) {
4812 print_implemented_interfaces (klass);
4814 for (i = 0; i <= max_iid; i++)
4815 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
4818 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&klass->byval_arg),
4819 klass->vtable_size, icount);
4821 for (i = 0; i < cur_slot; ++i) {
4826 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4827 mono_method_full_name (cm, TRUE));
4833 printf ("Interfaces %s.%s (max_iid = %d)\n", klass->name_space,
4834 klass->name, max_iid);
4836 for (i = 0; i < klass->interface_count; i++) {
4837 ic = klass->interfaces [i];
4838 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4839 mono_class_interface_offset (klass, ic),
4840 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4843 for (k = klass->parent; k ; k = k->parent) {
4844 for (i = 0; i < k->interface_count; i++) {
4845 ic = k->interfaces [i];
4846 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4847 mono_class_interface_offset (klass, ic),
4848 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4854 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (klass));
4859 char *name = mono_type_get_full_name (klass);
4860 mono_class_set_type_load_failure (klass, "VTable setup of type %s failed", name);
4863 g_hash_table_destroy (override_map);
4865 g_slist_free (virt_methods);
4870 * mono_method_get_vtable_slot:
4872 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4873 * LOCKING: Acquires the loader lock.
4875 * FIXME Use proper MonoError machinery here.
4878 mono_method_get_vtable_slot (MonoMethod *method)
4880 if (method->slot == -1) {
4881 mono_class_setup_vtable (method->klass);
4882 if (mono_class_has_failure (method->klass))
4884 if (method->slot == -1) {
4888 if (!method->klass->generic_class) {
4889 g_assert (method->is_inflated);
4890 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4893 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4894 g_assert (method->klass->generic_class);
4895 gklass = method->klass->generic_class->container_class;
4896 mono_class_setup_methods (method->klass);
4897 g_assert (method->klass->methods);
4898 for (i = 0; i < method->klass->method.count; ++i) {
4899 if (method->klass->methods [i] == method)
4902 g_assert (i < method->klass->method.count);
4903 g_assert (gklass->methods);
4904 method->slot = gklass->methods [i]->slot;
4906 g_assert (method->slot != -1);
4908 return method->slot;
4912 * mono_method_get_vtable_index:
4915 * Returns the index into the runtime vtable to access the method or,
4916 * in the case of a virtual generic method, the virtual generic method
4917 * thunk. Returns -1 on failure.
4919 * FIXME Use proper MonoError machinery here.
4922 mono_method_get_vtable_index (MonoMethod *method)
4924 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4925 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4926 if (imethod->declaring->is_generic)
4927 return mono_method_get_vtable_slot (imethod->declaring);
4929 return mono_method_get_vtable_slot (method);
4932 static MonoMethod *default_ghc = NULL;
4933 static MonoMethod *default_finalize = NULL;
4934 static int finalize_slot = -1;
4935 static int ghc_slot = -1;
4938 initialize_object_slots (MonoClass *klass)
4943 if (klass == mono_defaults.object_class) {
4944 mono_class_setup_vtable (klass);
4945 for (i = 0; i < klass->vtable_size; ++i) {
4946 MonoMethod *cm = klass->vtable [i];
4948 if (!strcmp (cm->name, "GetHashCode"))
4950 else if (!strcmp (cm->name, "Finalize"))
4954 g_assert (ghc_slot > 0);
4955 default_ghc = klass->vtable [ghc_slot];
4957 g_assert (finalize_slot > 0);
4958 default_finalize = klass->vtable [finalize_slot];
4963 MonoMethod *array_method;
4965 } GenericArrayMethodInfo;
4967 static int generic_array_method_num = 0;
4968 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4971 generic_array_methods (MonoClass *klass)
4973 int i, count_generic = 0;
4974 GList *list = NULL, *tmp;
4975 if (generic_array_method_num)
4976 return generic_array_method_num;
4977 mono_class_setup_methods (klass->parent); /*This is setting up System.Array*/
4978 g_assert (!mono_class_has_failure (klass->parent)); /*So hitting this assert is a huge problem*/
4979 for (i = 0; i < klass->parent->method.count; i++) {
4980 MonoMethod *m = klass->parent->methods [i];
4981 if (!strncmp (m->name, "InternalArray__", 15)) {
4983 list = g_list_prepend (list, m);
4986 list = g_list_reverse (list);
4987 generic_array_method_info = (GenericArrayMethodInfo *)mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4989 for (tmp = list; tmp; tmp = tmp->next) {
4990 const char *mname, *iname;
4992 MonoMethod *m = (MonoMethod *)tmp->data;
4993 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4994 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4996 generic_array_method_info [i].array_method = m;
4997 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4998 iname = "System.Collections.Generic.ICollection`1.";
4999 mname = m->name + 27;
5000 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
5001 iname = "System.Collections.Generic.IEnumerable`1.";
5002 mname = m->name + 27;
5003 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
5004 iname = "System.Collections.Generic.IReadOnlyList`1.";
5005 mname = m->name + strlen (ireadonlylist_prefix);
5006 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
5007 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
5008 mname = m->name + strlen (ireadonlycollection_prefix);
5009 } else if (!strncmp (m->name, "InternalArray__", 15)) {
5010 iname = "System.Collections.Generic.IList`1.";
5011 mname = m->name + 15;
5013 g_assert_not_reached ();
5016 name = (gchar *)mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
5017 strcpy (name, iname);
5018 strcpy (name + strlen (iname), mname);
5019 generic_array_method_info [i].name = name;
5022 /*g_print ("array generic methods: %d\n", count_generic);*/
5024 generic_array_method_num = count_generic;
5026 return generic_array_method_num;
5030 setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos)
5032 MonoGenericContext tmp_context;
5035 tmp_context.class_inst = NULL;
5036 tmp_context.method_inst = iface->generic_class->context.class_inst;
5037 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
5039 for (i = 0; i < generic_array_method_num; i++) {
5041 MonoMethod *m = generic_array_method_info [i].array_method;
5042 MonoMethod *inflated;
5044 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
5045 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
5046 methods [pos++] = mono_marshal_get_generic_array_helper (klass, iface, generic_array_method_info [i].name, inflated);
5051 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
5053 int null_length = strlen ("(null)");
5054 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
5055 char *s = (char *)mono_image_alloc (image, len);
5058 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
5059 g_assert (result == len - 1);
5066 * @class: the class to initialize
5068 * Compute the instance_size, class_size and other infos that cannot be
5069 * computed at mono_class_get() time. Also compute vtable_size if possible.
5070 * Returns TRUE on success or FALSE if there was a problem in loading
5071 * the type (incorrect assemblies, missing assemblies, methods, etc).
5073 * LOCKING: Acquires the loader lock.
5076 mono_class_init (MonoClass *klass)
5079 MonoCachedClassInfo cached_info;
5080 gboolean has_cached_info;
5084 /* Double-checking locking pattern */
5085 if (klass->inited || mono_class_has_failure (klass))
5086 return !mono_class_has_failure (klass);
5088 /*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/
5090 /* We do everything inside the lock to prevent races */
5091 mono_loader_lock ();
5093 if (klass->inited || mono_class_has_failure (klass)) {
5094 mono_loader_unlock ();
5095 /* Somebody might have gotten in before us */
5096 return !mono_class_has_failure (klass);
5099 if (klass->init_pending) {
5100 mono_class_set_type_load_failure (klass, "Recursive type definition detected");
5104 klass->init_pending = 1;
5106 if (mono_verifier_is_enabled_for_class (klass) && !mono_verifier_verify_class (klass)) {
5107 mono_class_set_type_load_failure (klass, "%s", concat_two_strings_with_zero (klass->image, klass->name, klass->image->assembly_name));
5112 if (klass->byval_arg.type == MONO_TYPE_ARRAY || klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5113 MonoClass *element_class = klass->element_class;
5114 if (!element_class->inited)
5115 mono_class_init (element_class);
5116 if (mono_class_has_failure (element_class)) {
5117 mono_class_set_type_load_failure (klass, "");
5122 mono_stats.initialized_class_count++;
5124 if (klass->generic_class && !klass->generic_class->is_dynamic) {
5125 MonoClass *gklass = klass->generic_class->container_class;
5127 mono_stats.generic_class_count++;
5129 klass->method = gklass->method;
5130 klass->field = gklass->field;
5132 mono_class_init (gklass);
5133 // FIXME: Why is this needed ?
5134 if (!mono_class_has_failure (gklass))
5135 mono_class_setup_methods (gklass);
5136 if (mono_class_has_failure (gklass)) {
5137 mono_class_set_type_load_failure (klass, "Generic Type Defintion failed to init");
5141 if (MONO_CLASS_IS_INTERFACE (klass))
5142 klass->interface_id = mono_get_unique_iid (klass);
5145 if (klass->parent && !klass->parent->inited)
5146 mono_class_init (klass->parent);
5148 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
5150 if (klass->generic_class || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
5151 klass->nested_classes_inited = TRUE;
5154 * Computes the size used by the fields, and their locations
5156 if (has_cached_info) {
5157 klass->instance_size = cached_info.instance_size;
5158 klass->sizes.class_size = cached_info.class_size;
5159 klass->packing_size = cached_info.packing_size;
5160 klass->min_align = cached_info.min_align;
5161 klass->blittable = cached_info.blittable;
5162 klass->has_references = cached_info.has_references;
5163 klass->has_static_refs = cached_info.has_static_refs;
5164 klass->no_special_static_fields = cached_info.no_special_static_fields;
5167 if (!klass->size_inited){
5168 mono_class_setup_fields (klass);
5169 if (mono_class_has_failure (klass))
5173 /* Initialize arrays */
5175 klass->method.count = 3 + (klass->rank > 1? 2: 1);
5177 if (klass->interface_count) {
5178 int count_generic = generic_array_methods (klass);
5179 klass->method.count += klass->interface_count * count_generic;
5183 mono_class_setup_supertypes (klass);
5186 initialize_object_slots (klass);
5189 * Initialize the rest of the data without creating a generic vtable if possible.
5190 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5191 * also avoid computing a generic vtable.
5193 if (has_cached_info) {
5195 klass->vtable_size = cached_info.vtable_size;
5196 klass->has_finalize = cached_info.has_finalize;
5197 klass->has_finalize_inited = TRUE;
5198 klass->ghcimpl = cached_info.ghcimpl;
5199 klass->has_cctor = cached_info.has_cctor;
5200 } else if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5201 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5202 * The first slot if for array with.
5204 static int szarray_vtable_size[2] = { 0 };
5206 int slot = MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg) ? 0 : 1;
5209 if (!szarray_vtable_size [slot]) {
5210 mono_class_setup_vtable (klass);
5211 szarray_vtable_size [slot] = klass->vtable_size;
5213 klass->vtable_size = szarray_vtable_size[slot];
5215 } else if (klass->generic_class && !MONO_CLASS_IS_INTERFACE (klass)) {
5216 MonoClass *gklass = klass->generic_class->container_class;
5218 /* Generic instance case */
5219 klass->ghcimpl = gklass->ghcimpl;
5220 klass->has_cctor = gklass->has_cctor;
5222 mono_class_setup_vtable (gklass);
5223 if (mono_class_has_failure (gklass)) {
5224 mono_class_set_type_load_failure (klass, "");
5228 klass->vtable_size = gklass->vtable_size;
5232 /* ghcimpl is not currently used
5234 if (klass->parent) {
5235 MonoMethod *cmethod = klass->vtable [ghc_slot];
5236 if (cmethod->is_inflated)
5237 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5238 if (cmethod == default_ghc) {
5244 /* C# doesn't allow interfaces to have cctors */
5245 if (!MONO_CLASS_IS_INTERFACE (klass) || klass->image != mono_defaults.corlib) {
5246 MonoMethod *cmethod = NULL;
5248 if (klass->type_token && !image_is_dynamic(klass->image)) {
5249 cmethod = find_method_in_metadata (klass, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5250 /* The find_method function ignores the 'flags' argument */
5251 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5252 klass->has_cctor = 1;
5254 mono_class_setup_methods (klass);
5255 if (mono_class_has_failure (klass))
5258 for (i = 0; i < klass->method.count; ++i) {
5259 MonoMethod *method = klass->methods [i];
5260 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5261 (strcmp (".cctor", method->name) == 0)) {
5262 klass->has_cctor = 1;
5270 if (klass->parent) {
5271 int first_iface_slot;
5272 /* This will compute klass->parent->vtable_size for some classes */
5273 mono_class_init (klass->parent);
5274 if (mono_class_has_failure (klass->parent)) {
5275 mono_class_set_type_load_failure (klass, "");
5278 if (!klass->parent->vtable_size) {
5279 /* FIXME: Get rid of this somehow */
5280 mono_class_setup_vtable (klass->parent);
5281 if (mono_class_has_failure (klass->parent)) {
5282 mono_class_set_type_load_failure (klass, "");
5286 first_iface_slot = klass->parent->vtable_size;
5287 if (mono_class_need_stelemref_method (klass))
5289 setup_interface_offsets (klass, first_iface_slot, TRUE);
5291 setup_interface_offsets (klass, 0, TRUE);
5294 if (mono_security_core_clr_enabled ())
5295 mono_security_core_clr_check_inheritance (klass);
5297 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass))
5298 mono_class_set_type_load_failure (klass, "Invalid generic instantiation");
5303 /* Because of the double-checking locking pattern */
5304 mono_memory_barrier ();
5306 klass->init_pending = 0;
5308 mono_loader_unlock ();
5310 return !mono_class_has_failure (klass);
5314 * mono_class_has_finalizer:
5316 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5320 mono_class_has_finalizer (MonoClass *klass)
5322 gboolean has_finalize = FALSE;
5324 if (klass->has_finalize_inited)
5325 return klass->has_finalize;
5327 /* Interfaces and valuetypes are not supposed to have finalizers */
5328 if (!(MONO_CLASS_IS_INTERFACE (klass) || klass->valuetype)) {
5329 MonoMethod *cmethod = NULL;
5331 if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5332 } else if (klass->generic_class) {
5333 MonoClass *gklass = klass->generic_class->container_class;
5335 has_finalize = mono_class_has_finalizer (gklass);
5336 } else if (klass->parent && klass->parent->has_finalize) {
5337 has_finalize = TRUE;
5339 if (klass->parent) {
5341 * Can't search in metadata for a method named Finalize, because that
5342 * ignores overrides.
5344 mono_class_setup_vtable (klass);
5345 if (mono_class_has_failure (klass))
5348 cmethod = klass->vtable [finalize_slot];
5352 g_assert (klass->vtable_size > finalize_slot);
5354 if (klass->parent) {
5355 if (cmethod->is_inflated)
5356 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5357 if (cmethod != default_finalize)
5358 has_finalize = TRUE;
5364 mono_image_lock (klass->image);
5366 if (!klass->has_finalize_inited) {
5367 klass->has_finalize = has_finalize ? 1 : 0;
5369 mono_memory_barrier ();
5370 klass->has_finalize_inited = TRUE;
5373 mono_image_unlock (klass->image);
5375 return klass->has_finalize;
5379 mono_is_corlib_image (MonoImage *image)
5381 /* FIXME: allow the dynamic case for our compilers and with full trust */
5382 if (image_is_dynamic (image))
5383 return image->assembly && !strcmp (image->assembly->aname.name, "mscorlib");
5385 return image == mono_defaults.corlib;
5389 * LOCKING: this assumes the loader lock is held
5392 mono_class_setup_mono_type (MonoClass *klass)
5394 const char *name = klass->name;
5395 const char *nspace = klass->name_space;
5396 gboolean is_corlib = mono_is_corlib_image (klass->image);
5398 klass->this_arg.byref = 1;
5399 klass->this_arg.data.klass = klass;
5400 klass->this_arg.type = MONO_TYPE_CLASS;
5401 klass->byval_arg.data.klass = klass;
5402 klass->byval_arg.type = MONO_TYPE_CLASS;
5404 if (is_corlib && !strcmp (nspace, "System")) {
5405 if (!strcmp (name, "ValueType")) {
5407 * do not set the valuetype bit for System.ValueType.
5408 * klass->valuetype = 1;
5410 klass->blittable = TRUE;
5411 } else if (!strcmp (name, "Enum")) {
5413 * do not set the valuetype bit for System.Enum.
5414 * klass->valuetype = 1;
5416 klass->valuetype = 0;
5417 klass->enumtype = 0;
5418 } else if (!strcmp (name, "Object")) {
5419 klass->byval_arg.type = MONO_TYPE_OBJECT;
5420 klass->this_arg.type = MONO_TYPE_OBJECT;
5421 } else if (!strcmp (name, "String")) {
5422 klass->byval_arg.type = MONO_TYPE_STRING;
5423 klass->this_arg.type = MONO_TYPE_STRING;
5424 } else if (!strcmp (name, "TypedReference")) {
5425 klass->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5426 klass->this_arg.type = MONO_TYPE_TYPEDBYREF;
5430 if (klass->valuetype) {
5431 int t = MONO_TYPE_VALUETYPE;
5433 if (is_corlib && !strcmp (nspace, "System")) {
5436 if (!strcmp (name, "Boolean")) {
5437 t = MONO_TYPE_BOOLEAN;
5438 } else if (!strcmp(name, "Byte")) {
5440 klass->blittable = TRUE;
5444 if (!strcmp (name, "Char")) {
5449 if (!strcmp (name, "Double")) {
5451 klass->blittable = TRUE;
5455 if (!strcmp (name, "Int32")) {
5457 klass->blittable = TRUE;
5458 } else if (!strcmp(name, "Int16")) {
5460 klass->blittable = TRUE;
5461 } else if (!strcmp(name, "Int64")) {
5463 klass->blittable = TRUE;
5464 } else if (!strcmp(name, "IntPtr")) {
5466 klass->blittable = TRUE;
5470 if (!strcmp (name, "Single")) {
5472 klass->blittable = TRUE;
5473 } else if (!strcmp(name, "SByte")) {
5475 klass->blittable = TRUE;
5479 if (!strcmp (name, "UInt32")) {
5481 klass->blittable = TRUE;
5482 } else if (!strcmp(name, "UInt16")) {
5484 klass->blittable = TRUE;
5485 } else if (!strcmp(name, "UInt64")) {
5487 klass->blittable = TRUE;
5488 } else if (!strcmp(name, "UIntPtr")) {
5490 klass->blittable = TRUE;
5494 if (!strcmp (name, "TypedReference")) {
5495 t = MONO_TYPE_TYPEDBYREF;
5496 klass->blittable = TRUE;
5500 if (!strcmp (name, "Void")) {
5508 klass->byval_arg.type = (MonoTypeEnum)t;
5509 klass->this_arg.type = (MonoTypeEnum)t;
5512 if (MONO_CLASS_IS_INTERFACE (klass))
5513 klass->interface_id = mono_get_unique_iid (klass);
5519 * COM initialization is delayed until needed.
5520 * However when a [ComImport] attribute is present on a type it will trigger
5521 * the initialization. This is not a problem unless the BCL being executed
5522 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5525 init_com_from_comimport (MonoClass *klass)
5527 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5528 if (mono_security_core_clr_enabled ()) {
5529 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5530 if (!mono_security_core_clr_determine_platform_image (klass->image)) {
5531 /* but it can not be made available for application (i.e. user code) since all COM calls
5532 * are considered native calls. In this case we fail with a TypeLoadException (just like
5533 * Silverlight 2 does */
5534 mono_class_set_type_load_failure (klass, "");
5539 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5541 #endif /*DISABLE_COM*/
5544 * LOCKING: this assumes the loader lock is held
5547 mono_class_setup_parent (MonoClass *klass, MonoClass *parent)
5549 gboolean system_namespace;
5550 gboolean is_corlib = mono_is_corlib_image (klass->image);
5552 system_namespace = !strcmp (klass->name_space, "System") && is_corlib;
5554 /* if root of the hierarchy */
5555 if (system_namespace && !strcmp (klass->name, "Object")) {
5556 klass->parent = NULL;
5557 klass->instance_size = sizeof (MonoObject);
5560 if (!strcmp (klass->name, "<Module>")) {
5561 klass->parent = NULL;
5562 klass->instance_size = 0;
5566 if (!MONO_CLASS_IS_INTERFACE (klass)) {
5567 /* Imported COM Objects always derive from __ComObject. */
5569 if (MONO_CLASS_IS_IMPORT (klass)) {
5570 init_com_from_comimport (klass);
5571 if (parent == mono_defaults.object_class)
5572 parent = mono_class_get_com_object_class ();
5576 /* set the parent to something useful and safe, but mark the type as broken */
5577 parent = mono_defaults.object_class;
5578 mono_class_set_type_load_failure (klass, "");
5581 klass->parent = parent;
5583 if (parent->generic_class && !parent->name) {
5585 * If the parent is a generic instance, we may get
5586 * called before it is fully initialized, especially
5587 * before it has its name.
5592 #ifndef DISABLE_REMOTING
5593 klass->marshalbyref = parent->marshalbyref;
5594 klass->contextbound = parent->contextbound;
5597 klass->delegate = parent->delegate;
5599 if (MONO_CLASS_IS_IMPORT (klass) || mono_class_is_com_object (parent))
5600 mono_class_set_is_com_object (klass);
5602 if (system_namespace) {
5603 #ifndef DISABLE_REMOTING
5604 if (klass->name [0] == 'M' && !strcmp (klass->name, "MarshalByRefObject"))
5605 klass->marshalbyref = 1;
5607 if (klass->name [0] == 'C' && !strcmp (klass->name, "ContextBoundObject"))
5608 klass->contextbound = 1;
5610 if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate"))
5611 klass->delegate = 1;
5614 if (klass->parent->enumtype || (mono_is_corlib_image (klass->parent->image) && (strcmp (klass->parent->name, "ValueType") == 0) &&
5615 (strcmp (klass->parent->name_space, "System") == 0)))
5616 klass->valuetype = 1;
5617 if (mono_is_corlib_image (klass->parent->image) && ((strcmp (klass->parent->name, "Enum") == 0) && (strcmp (klass->parent->name_space, "System") == 0))) {
5618 klass->valuetype = klass->enumtype = 1;
5620 /*klass->enumtype = klass->parent->enumtype; */
5622 /* initialize com types if COM interfaces are present */
5624 if (MONO_CLASS_IS_IMPORT (klass))
5625 init_com_from_comimport (klass);
5627 klass->parent = NULL;
5633 * mono_class_setup_supertypes:
5636 * Build the data structure needed to make fast type checks work.
5637 * This currently sets two fields in @class:
5638 * - idepth: distance between @class and System.Object in the type
5640 * - supertypes: array of classes: each element has a class in the hierarchy
5641 * starting from @class up to System.Object
5643 * LOCKING: This function is atomic, in case of contention we waste memory.
5646 mono_class_setup_supertypes (MonoClass *klass)
5649 MonoClass **supertypes;
5651 mono_atomic_load_acquire (supertypes, MonoClass **, &klass->supertypes);
5655 if (klass->parent && !klass->parent->supertypes)
5656 mono_class_setup_supertypes (klass->parent);
5658 klass->idepth = klass->parent->idepth + 1;
5662 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, klass->idepth);
5663 supertypes = (MonoClass **)mono_class_alloc0 (klass, sizeof (MonoClass *) * ms);
5665 if (klass->parent) {
5666 CHECKED_METADATA_WRITE_PTR ( supertypes [klass->idepth - 1] , klass );
5669 for (supertype_idx = 0; supertype_idx < klass->parent->idepth; supertype_idx++)
5670 CHECKED_METADATA_WRITE_PTR ( supertypes [supertype_idx] , klass->parent->supertypes [supertype_idx] );
5672 CHECKED_METADATA_WRITE_PTR ( supertypes [0] , klass );
5675 CHECKED_METADATA_WRITE_PTR_ATOMIC ( klass->supertypes , supertypes );
5679 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5681 MonoClass *gtd = (MonoClass*)user_data;
5682 /* Only try to fix generic instances of @gtd */
5683 if (gclass->generic_class->container_class != gtd)
5686 /* Check if the generic instance has no parent. */
5687 if (gtd->parent && !gclass->parent)
5688 mono_generic_class_setup_parent (gclass, gtd);
5694 mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char *msg)
5696 mono_class_set_type_load_failure (klass, "%s", msg);
5697 mono_error_set_type_load_class (error, klass, "%s", msg);
5701 * mono_class_create_from_typedef:
5702 * @image: image where the token is valid
5703 * @type_token: typedef token
5704 * @error: used to return any error found while creating the type
5706 * Create the MonoClass* representing the specified type token.
5707 * @type_token must be a TypeDef token.
5709 * FIXME: don't return NULL on failure, just the the caller figure it out.
5712 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5714 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5715 MonoClass *klass, *parent = NULL;
5716 guint32 cols [MONO_TYPEDEF_SIZE];
5717 guint32 cols_next [MONO_TYPEDEF_SIZE];
5718 guint tidx = mono_metadata_token_index (type_token);
5719 MonoGenericContext *context = NULL;
5720 const char *name, *nspace;
5722 MonoClass **interfaces;
5723 guint32 field_last, method_last;
5724 guint32 nesting_tokeen;
5726 mono_error_init (error);
5728 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5729 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5733 mono_loader_lock ();
5735 if ((klass = (MonoClass *)mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5736 mono_loader_unlock ();
5740 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5742 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5743 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5745 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
5748 klass->name_space = nspace;
5750 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5752 klass->image = image;
5753 klass->type_token = type_token;
5754 klass->flags = cols [MONO_TYPEDEF_FLAGS];
5756 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
5758 classes_size += sizeof (MonoClass);
5761 * Check whether we're a generic type definition.
5763 klass->generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
5764 if (klass->generic_container) {
5765 klass->is_generic = 1;
5766 klass->generic_container->owner.klass = klass;
5767 klass->generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
5768 context = &klass->generic_container->context;
5771 if (klass->generic_container)
5772 enable_gclass_recording ();
5774 if (cols [MONO_TYPEDEF_EXTENDS]) {
5776 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5778 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5779 /*WARNING: this must satisfy mono_metadata_type_hash*/
5780 klass->this_arg.byref = 1;
5781 klass->this_arg.data.klass = klass;
5782 klass->this_arg.type = MONO_TYPE_CLASS;
5783 klass->byval_arg.data.klass = klass;
5784 klass->byval_arg.type = MONO_TYPE_CLASS;
5786 parent = mono_class_get_checked (image, parent_token, error);
5787 if (parent && context) /* Always inflate */
5788 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5790 if (parent == NULL) {
5791 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5792 goto parent_failure;
5795 for (tmp = parent; tmp; tmp = tmp->parent) {
5797 mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
5798 goto parent_failure;
5800 if (klass->generic_container && tmp->generic_class && tmp->generic_class->container_class == klass) {
5801 mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
5802 goto parent_failure;
5807 mono_class_setup_parent (klass, parent);
5809 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5810 mono_class_setup_mono_type (klass);
5812 if (klass->generic_container)
5813 disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
5816 * This might access klass->byval_arg for recursion generated by generic constraints,
5817 * so it has to come after setup_mono_type ().
5819 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5820 klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5821 if (!mono_error_ok (error)) {
5822 /*FIXME implement a mono_class_set_failure_from_mono_error */
5823 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5824 mono_loader_unlock ();
5825 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5830 if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5834 if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5838 klass->cast_class = klass->element_class = klass;
5840 if (!klass->enumtype) {
5841 if (!mono_metadata_interfaces_from_typedef_full (
5842 image, type_token, &interfaces, &icount, FALSE, context, error)){
5844 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5845 mono_loader_unlock ();
5846 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5850 klass->interfaces = interfaces;
5851 klass->interface_count = icount;
5852 klass->interfaces_inited = 1;
5855 /*g_print ("Load class %s\n", name);*/
5858 * Compute the field and method lists
5860 klass->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5861 klass->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5863 if (tt->rows > tidx){
5864 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5865 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5866 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5868 field_last = image->tables [MONO_TABLE_FIELD].rows;
5869 method_last = image->tables [MONO_TABLE_METHOD].rows;
5872 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5873 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5874 klass->field.count = field_last - klass->field.first;
5876 klass->field.count = 0;
5878 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5879 klass->method.count = method_last - klass->method.first;
5881 klass->method.count = 0;
5883 /* reserve space to store vector pointer in arrays */
5884 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5885 klass->instance_size += 2 * sizeof (gpointer);
5886 g_assert (klass->field.count == 0);
5889 if (klass->enumtype) {
5890 MonoType *enum_basetype = mono_class_find_enum_basetype (klass, error);
5891 if (!enum_basetype) {
5892 /*set it to a default value as the whole runtime can't handle this to be null*/
5893 klass->cast_class = klass->element_class = mono_defaults.int32_class;
5894 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5895 mono_loader_unlock ();
5896 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5899 klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
5903 * If we're a generic type definition, load the constraints.
5904 * We must do this after the class has been constructed to make certain recursive scenarios
5907 if (klass->generic_container && !mono_metadata_load_generic_param_constraints_checked (image, type_token, klass->generic_container, error)) {
5908 mono_class_set_type_load_failure (klass, "Could not load generic parameter constrains due to %s", mono_error_get_message (error));
5909 mono_loader_unlock ();
5910 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5914 if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5915 if (!strncmp (name, "Vector", 6))
5916 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");
5919 mono_loader_unlock ();
5921 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5926 mono_class_setup_mono_type (klass);
5927 mono_loader_unlock ();
5928 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5932 /** Is klass a Nullable<T> ginst? */
5934 mono_class_is_nullable (MonoClass *klass)
5936 return klass->generic_class != NULL &&
5937 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5941 /** if klass is T? return T */
5943 mono_class_get_nullable_param (MonoClass *klass)
5945 g_assert (mono_class_is_nullable (klass));
5946 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5950 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5954 MonoGenericClass *gclass = klass->generic_class;
5956 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5957 if (!mono_error_ok (&error)) {
5958 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5959 klass->parent = mono_defaults.object_class;
5960 mono_class_set_type_load_failure (klass, "");
5961 mono_error_cleanup (&error);
5965 mono_class_setup_parent (klass, klass->parent);
5967 if (klass->enumtype) {
5968 klass->cast_class = gtd->cast_class;
5969 klass->element_class = gtd->element_class;
5975 * Create the `MonoClass' for an instantiation of a generic type.
5976 * We only do this if we actually need it.
5979 mono_generic_class_get_class (MonoGenericClass *gclass)
5981 MonoClass *klass, *gklass;
5983 if (gclass->cached_class)
5984 return gclass->cached_class;
5986 mono_loader_lock ();
5987 if (gclass->cached_class) {
5988 mono_loader_unlock ();
5989 return gclass->cached_class;
5992 klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
5994 gklass = gclass->container_class;
5996 if (record_gclass_instantiation > 0)
5997 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
5999 if (gklass->nested_in) {
6000 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
6001 klass->nested_in = gklass->nested_in;
6004 klass->name = gklass->name;
6005 klass->name_space = gklass->name_space;
6007 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6009 klass->image = gklass->image;
6010 klass->flags = gklass->flags;
6011 klass->type_token = gklass->type_token;
6012 klass->field.count = gklass->field.count;
6014 klass->is_inflated = 1;
6015 klass->generic_class = gclass;
6017 klass->byval_arg.type = MONO_TYPE_GENERICINST;
6018 klass->this_arg.type = klass->byval_arg.type;
6019 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
6020 klass->this_arg.byref = TRUE;
6021 klass->enumtype = gklass->enumtype;
6022 klass->valuetype = gklass->valuetype;
6024 klass->cast_class = klass->element_class = klass;
6026 if (mono_class_is_nullable (klass))
6027 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
6030 * We're not interested in the nested classes of a generic instance.
6031 * We use the generic type definition to look for nested classes.
6034 mono_generic_class_setup_parent (klass, gklass);
6036 if (gclass->is_dynamic) {
6038 * 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.
6039 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
6040 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
6042 if (!gklass->wastypebuilder)
6045 mono_class_setup_supertypes (klass);
6047 if (klass->enumtype) {
6049 * For enums, gklass->fields might not been set, but instance_size etc. is
6050 * already set in mono_reflection_create_internal_class (). For non-enums,
6051 * these will be computed normally in mono_class_layout_fields ().
6053 klass->instance_size = gklass->instance_size;
6054 klass->sizes.class_size = gklass->sizes.class_size;
6055 mono_memory_barrier ();
6056 klass->size_inited = 1;
6060 mono_memory_barrier ();
6061 gclass->cached_class = klass;
6063 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6065 inflated_classes ++;
6066 inflated_classes_size += sizeof (MonoClass);
6068 mono_loader_unlock ();
6074 get_image_for_container (MonoGenericContainer *container)
6077 if (container->is_anonymous) {
6078 result = container->owner.image;
6081 if (container->is_method) {
6082 MonoMethod *method = container->owner.method;
6083 g_assert_checked (method);
6084 klass = method->klass;
6086 klass = container->owner.klass;
6088 g_assert_checked (klass);
6089 result = klass->image;
6096 get_image_for_generic_param (MonoGenericParam *param)
6098 MonoGenericContainer *container = mono_generic_param_owner (param);
6099 g_assert_checked (container);
6100 return get_image_for_container (container);
6103 // Make a string in the designated image consisting of a single integer.
6104 #define INT_STRING_SIZE 16
6106 make_generic_name_string (MonoImage *image, int num)
6108 char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
6109 g_snprintf (name, INT_STRING_SIZE, "%d", num);
6113 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
6114 // pinfo is derived from param by the caller for us.
6116 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
6118 MonoClass *klass, **ptr;
6120 MonoGenericContainer *container = mono_generic_param_owner (param);
6121 g_assert_checked (container);
6123 MonoImage *image = get_image_for_container (container);
6124 gboolean is_mvar = container->is_method;
6125 gboolean is_anonymous = container->is_anonymous;
6127 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6128 classes_size += sizeof (MonoClass);
6131 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
6133 int n = mono_generic_param_num (param);
6134 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
6138 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , "" );
6139 } else if (is_mvar) {
6140 MonoMethod *omethod = container->owner.method;
6141 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
6143 MonoClass *oklass = container->owner.klass;
6144 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
6147 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6149 // Count non-NULL items in pinfo->constraints
6152 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6156 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6157 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
6159 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
6160 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
6162 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
6165 if (count - pos > 0) {
6166 klass->interface_count = count - pos;
6167 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
6168 klass->interfaces_inited = TRUE;
6169 for (i = pos; i < count; i++)
6170 CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
6173 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
6175 klass->inited = TRUE;
6176 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class , klass );
6177 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
6178 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
6180 klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6181 klass->this_arg.type = klass->byval_arg.type;
6182 CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param , param );
6183 CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
6184 klass->this_arg.byref = TRUE;
6186 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6187 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6189 /*Init these fields to sane values*/
6190 klass->min_align = 1;
6192 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6193 * constrained to, the JIT depends on this.
6195 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6196 mono_memory_barrier ();
6197 klass->size_inited = 1;
6198 klass->setup_fields_called = 1;
6200 mono_class_setup_supertypes (klass);
6202 if (count - pos > 0) {
6203 mono_class_setup_vtable (klass->parent);
6204 if (mono_class_has_failure (klass->parent))
6205 mono_class_set_type_load_failure (klass, "Failed to setup parent interfaces");
6207 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6213 #define FAST_CACHE_SIZE 16
6216 * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6217 * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6218 * we cache the MonoClasses.
6219 * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6220 * LOCKING: Takes the image lock depending on @take_lock.
6223 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6225 int n = mono_generic_param_num (param);
6226 MonoImage *image = get_image_for_generic_param (param);
6227 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6228 MonoClass *klass = NULL;
6233 // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6234 // For high numbers or constraints we have to use pointer hashes.
6235 if (param->gshared_constraint) {
6236 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6239 mono_image_lock (image);
6240 klass = (MonoClass *)g_hash_table_lookup (ht, param);
6242 mono_image_unlock (image);
6247 if (n < FAST_CACHE_SIZE) {
6249 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6251 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6253 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6256 mono_image_lock (image);
6257 klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6259 mono_image_unlock (image);
6266 * LOCKING: Image lock (param->image) must be held
6269 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6271 int n = mono_generic_param_num (param);
6272 MonoImage *image = get_image_for_generic_param (param);
6273 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6277 if (param->gshared_constraint) {
6278 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6280 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6281 mono_memory_barrier ();
6283 image->mvar_cache_constrained = ht;
6285 image->var_cache_constrained = ht;
6287 g_hash_table_insert (ht, param, klass);
6288 } else if (n < FAST_CACHE_SIZE) {
6290 /* Requires locking to avoid droping an already published class */
6291 if (!image->mvar_cache_fast)
6292 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6293 image->mvar_cache_fast [n] = klass;
6295 if (!image->var_cache_fast)
6296 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6297 image->var_cache_fast [n] = klass;
6300 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6302 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6304 ht = g_hash_table_new (NULL, NULL);
6305 mono_memory_barrier ();
6307 image->mvar_cache_slow = ht;
6309 image->var_cache_slow = ht;
6312 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6317 * LOCKING: Acquires the image lock (@image).
6320 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6322 MonoImage *image = get_image_for_generic_param (param);
6323 MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6324 MonoClass *klass, *klass2;
6326 // If a klass already exists for this object and is cached, return it.
6327 if (pinfo) // Non-anonymous
6328 klass = pinfo->pklass;
6330 klass = get_anon_gparam_class (param, TRUE);
6335 // Create a new klass
6336 klass = make_generic_param_class (param, pinfo);
6338 // Now we need to cache the klass we created.
6339 // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6340 // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6341 // and allow our newly-created klass object to just leak.
6342 mono_memory_barrier ();
6344 mono_image_lock (image);
6346 // Here "klass2" refers to the klass potentially created by the other thread.
6347 if (pinfo) // Repeat check from above
6348 klass2 = pinfo->pklass;
6350 klass2 = get_anon_gparam_class (param, FALSE);
6357 pinfo->pklass = klass;
6359 set_anon_gparam_class (param, klass);
6361 mono_image_unlock (image);
6363 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6365 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED); // Alert profiler about botched class create
6367 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6373 * mono_class_from_generic_parameter:
6374 * @param: Parameter to find/construct a class for.
6375 * @arg2: Is ignored.
6376 * @arg3: Is ignored.
6379 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6381 return mono_class_from_generic_parameter_internal (param);
6386 mono_ptr_class_get (MonoType *type)
6389 MonoClass *el_class;
6393 el_class = mono_class_from_mono_type (type);
6394 image = el_class->image;
6396 mono_image_lock (image);
6397 if (image->ptr_cache) {
6398 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6399 mono_image_unlock (image);
6403 mono_image_unlock (image);
6405 result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6407 classes_size += sizeof (MonoClass);
6409 result->parent = NULL; /* no parent for PTR types */
6410 result->name_space = el_class->name_space;
6411 name = g_strdup_printf ("%s*", el_class->name);
6412 result->name = mono_image_strdup (image, name);
6415 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6417 result->image = el_class->image;
6418 result->inited = TRUE;
6419 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6420 /* Can pointers get boxed? */
6421 result->instance_size = sizeof (gpointer);
6422 result->cast_class = result->element_class = el_class;
6423 result->blittable = TRUE;
6425 result->byval_arg.type = MONO_TYPE_PTR;
6426 result->this_arg.type = result->byval_arg.type;
6427 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6428 result->this_arg.byref = TRUE;
6430 mono_class_setup_supertypes (result);
6432 mono_image_lock (image);
6433 if (image->ptr_cache) {
6435 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6436 mono_image_unlock (image);
6437 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6441 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6443 g_hash_table_insert (image->ptr_cache, el_class, result);
6444 mono_image_unlock (image);
6446 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6452 mono_fnptr_class_get (MonoMethodSignature *sig)
6455 static GHashTable *ptr_hash = NULL;
6457 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6459 mono_loader_lock ();
6462 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6464 if ((result = (MonoClass *)g_hash_table_lookup (ptr_hash, sig))) {
6465 mono_loader_unlock ();
6468 result = g_new0 (MonoClass, 1);
6470 result->parent = NULL; /* no parent for PTR types */
6471 result->name_space = "System";
6472 result->name = "MonoFNPtrFakeClass";
6474 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6476 result->image = mono_defaults.corlib; /* need to fix... */
6477 result->inited = TRUE;
6478 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6479 /* Can pointers get boxed? */
6480 result->instance_size = sizeof (gpointer);
6481 result->cast_class = result->element_class = result;
6482 result->blittable = TRUE;
6484 result->byval_arg.type = MONO_TYPE_FNPTR;
6485 result->this_arg.type = result->byval_arg.type;
6486 result->this_arg.data.method = result->byval_arg.data.method = sig;
6487 result->this_arg.byref = TRUE;
6488 result->blittable = TRUE;
6490 mono_class_setup_supertypes (result);
6492 g_hash_table_insert (ptr_hash, sig, result);
6494 mono_loader_unlock ();
6496 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6502 * mono_class_from_mono_type:
6503 * @type: describes the type to return
6505 * This returns a MonoClass for the specified MonoType, the value is never NULL.
6508 mono_class_from_mono_type (MonoType *type)
6510 switch (type->type) {
6511 case MONO_TYPE_OBJECT:
6512 return type->data.klass? type->data.klass: mono_defaults.object_class;
6513 case MONO_TYPE_VOID:
6514 return type->data.klass? type->data.klass: mono_defaults.void_class;
6515 case MONO_TYPE_BOOLEAN:
6516 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6517 case MONO_TYPE_CHAR:
6518 return type->data.klass? type->data.klass: mono_defaults.char_class;
6520 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6522 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6524 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6526 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6528 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6530 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6532 return type->data.klass? type->data.klass: mono_defaults.int_class;
6534 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6536 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6538 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6540 return type->data.klass? type->data.klass: mono_defaults.single_class;
6542 return type->data.klass? type->data.klass: mono_defaults.double_class;
6543 case MONO_TYPE_STRING:
6544 return type->data.klass? type->data.klass: mono_defaults.string_class;
6545 case MONO_TYPE_TYPEDBYREF:
6546 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6547 case MONO_TYPE_ARRAY:
6548 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6550 return mono_ptr_class_get (type->data.type);
6551 case MONO_TYPE_FNPTR:
6552 return mono_fnptr_class_get (type->data.method);
6553 case MONO_TYPE_SZARRAY:
6554 return mono_array_class_get (type->data.klass, 1);
6555 case MONO_TYPE_CLASS:
6556 case MONO_TYPE_VALUETYPE:
6557 return type->data.klass;
6558 case MONO_TYPE_GENERICINST:
6559 return mono_generic_class_get_class (type->data.generic_class);
6560 case MONO_TYPE_MVAR:
6562 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6564 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6565 g_assert_not_reached ();
6568 // Yes, this returns NULL, even if it is documented as not doing so, but there
6569 // is no way for the code to make it this far, due to the assert above.
6574 * mono_type_retrieve_from_typespec
6575 * @image: context where the image is created
6576 * @type_spec: typespec token
6577 * @context: the generic context used to evaluate generic instantiations in
6580 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6582 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6584 *did_inflate = FALSE;
6589 if (context && (context->class_inst || context->method_inst)) {
6590 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6592 if (!mono_error_ok (error)) {
6598 *did_inflate = TRUE;
6605 * mono_class_create_from_typespec
6606 * @image: context where the image is created
6607 * @type_spec: typespec token
6608 * @context: the generic context used to evaluate generic instantiations in
6611 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6614 gboolean inflated = FALSE;
6615 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6616 return_val_if_nok (error, NULL);
6617 ret = mono_class_from_mono_type (t);
6619 mono_metadata_free_type (t);
6624 * mono_bounded_array_class_get:
6625 * @element_class: element class
6626 * @rank: the dimension of the array class
6627 * @bounded: whenever the array has non-zero bounds
6629 * Returns: A class object describing the array with element type @element_type and
6633 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6637 MonoClass *parent = NULL;
6638 GSList *list, *rootlist = NULL;
6641 gboolean corlib_type = FALSE;
6643 g_assert (rank <= 255);
6646 /* bounded only matters for one-dimensional arrays */
6649 image = eclass->image;
6651 if (rank == 1 && !bounded) {
6653 * This case is very frequent not just during compilation because of calls
6654 * from mono_class_from_mono_type (), mono_array_new (),
6655 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6657 mono_os_mutex_lock (&image->szarray_cache_lock);
6658 if (!image->szarray_cache)
6659 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6660 klass = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6661 mono_os_mutex_unlock (&image->szarray_cache_lock);
6665 mono_loader_lock ();
6667 mono_loader_lock ();
6669 if (!image->array_cache)
6670 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6672 if ((rootlist = list = (GSList *)g_hash_table_lookup (image->array_cache, eclass))) {
6673 for (; list; list = list->next) {
6674 klass = (MonoClass *)list->data;
6675 if ((klass->rank == rank) && (klass->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6676 mono_loader_unlock ();
6683 /* for the building corlib use System.Array from it */
6684 if (image->assembly && assembly_is_dynamic (image->assembly) && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6685 parent = mono_class_load_from_name (image, "System", "Array");
6688 parent = mono_defaults.array_class;
6689 if (!parent->inited)
6690 mono_class_init (parent);
6693 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6695 klass->image = image;
6696 klass->name_space = eclass->name_space;
6697 nsize = strlen (eclass->name);
6698 name = (char *)g_malloc (nsize + 2 + rank + 1);
6699 memcpy (name, eclass->name, nsize);
6702 memset (name + nsize + 1, ',', rank - 1);
6704 name [nsize + rank] = '*';
6705 name [nsize + rank + bounded] = ']';
6706 name [nsize + rank + bounded + 1] = 0;
6707 klass->name = mono_image_strdup (image, name);
6710 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6712 classes_size += sizeof (MonoClass);
6714 klass->type_token = 0;
6715 /* all arrays are marked serializable and sealed, bug #42779 */
6716 klass->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6717 klass->parent = parent;
6718 klass->instance_size = mono_class_instance_size (klass->parent);
6720 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6721 /*Arrays of those two types are invalid.*/
6722 MonoError prepared_error;
6723 mono_error_init (&prepared_error);
6724 mono_error_set_invalid_program (&prepared_error, "Arrays of void or System.TypedReference types are invalid.");
6725 mono_class_set_failure (klass, MONO_EXCEPTION_INVALID_PROGRAM, mono_error_box (&prepared_error, klass->image));
6726 mono_error_cleanup (&prepared_error);
6727 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6728 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6729 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6730 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6732 /* element_size -1 is ok as this is not an instantitable type*/
6733 klass->sizes.element_size = -1;
6735 klass->sizes.element_size = mono_class_array_element_size (eclass);
6737 mono_class_setup_supertypes (klass);
6739 if (eclass->generic_class)
6740 mono_class_init (eclass);
6741 if (!eclass->size_inited)
6742 mono_class_setup_fields (eclass);
6743 if (mono_class_has_failure (eclass)) /*FIXME we fail the array type, but we have to let other fields be set.*/
6744 mono_class_set_type_load_failure (klass, "");
6746 klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6750 if (eclass->enumtype)
6751 klass->cast_class = eclass->element_class;
6753 klass->cast_class = eclass;
6755 switch (klass->cast_class->byval_arg.type) {
6757 klass->cast_class = mono_defaults.byte_class;
6760 klass->cast_class = mono_defaults.int16_class;
6763 #if SIZEOF_VOID_P == 4
6767 klass->cast_class = mono_defaults.int32_class;
6770 #if SIZEOF_VOID_P == 8
6774 klass->cast_class = mono_defaults.int64_class;
6780 klass->element_class = eclass;
6782 if ((rank > 1) || bounded) {
6783 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6784 klass->byval_arg.type = MONO_TYPE_ARRAY;
6785 klass->byval_arg.data.array = at;
6786 at->eklass = eclass;
6788 /* FIXME: complete.... */
6790 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6791 klass->byval_arg.data.klass = eclass;
6793 klass->this_arg = klass->byval_arg;
6794 klass->this_arg.byref = 1;
6799 klass->generic_container = eclass->generic_container;
6801 if (rank == 1 && !bounded) {
6802 MonoClass *prev_class;
6804 mono_os_mutex_lock (&image->szarray_cache_lock);
6805 prev_class = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6807 /* Someone got in before us */
6810 g_hash_table_insert (image->szarray_cache, eclass, klass);
6811 mono_os_mutex_unlock (&image->szarray_cache_lock);
6813 list = g_slist_append (rootlist, klass);
6814 g_hash_table_insert (image->array_cache, eclass, list);
6817 mono_loader_unlock ();
6819 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6825 * mono_array_class_get:
6826 * @element_class: element class
6827 * @rank: the dimension of the array class
6829 * Returns: A class object describing the array with element type @element_type and
6833 mono_array_class_get (MonoClass *eclass, guint32 rank)
6835 return mono_bounded_array_class_get (eclass, rank, FALSE);
6839 * mono_class_instance_size:
6842 * Use to get the size of a class in bytes.
6844 * Returns: The size of an object instance
6847 mono_class_instance_size (MonoClass *klass)
6849 if (!klass->size_inited)
6850 mono_class_init (klass);
6852 return klass->instance_size;
6856 * mono_class_min_align:
6859 * Use to get the computed minimum alignment requirements for the specified class.
6861 * Returns: minimm alignment requirements
6864 mono_class_min_align (MonoClass *klass)
6866 if (!klass->size_inited)
6867 mono_class_init (klass);
6869 return klass->min_align;
6873 * mono_class_value_size:
6876 * This function is used for value types, and return the
6877 * space and the alignment to store that kind of value object.
6879 * Returns: the size of a value of kind @klass
6882 mono_class_value_size (MonoClass *klass, guint32 *align)
6886 /* fixme: check disable, because we still have external revereces to
6887 * mscorlib and Dummy Objects
6889 /*g_assert (klass->valuetype);*/
6891 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6894 *align = klass->min_align;
6900 * mono_class_data_size:
6903 * Returns: The size of the static class data
6906 mono_class_data_size (MonoClass *klass)
6909 mono_class_init (klass);
6910 /* This can happen with dynamically created types */
6911 if (!klass->fields_inited)
6912 mono_class_setup_fields_locking (klass);
6914 /* in arrays, sizes.class_size is unioned with element_size
6915 * and arrays have no static fields
6919 return klass->sizes.class_size;
6923 * Auxiliary routine to mono_class_get_field
6925 * Takes a field index instead of a field token.
6927 static MonoClassField *
6928 mono_class_get_field_idx (MonoClass *klass, int idx)
6930 mono_class_setup_fields_locking (klass);
6931 if (mono_class_has_failure (klass))
6935 if (klass->image->uncompressed_metadata) {
6937 * klass->field.first points to the FieldPtr table, while idx points into the
6938 * Field table, so we have to do a search.
6940 /*FIXME this is broken for types with multiple fields with the same name.*/
6941 const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6944 for (i = 0; i < klass->field.count; ++i)
6945 if (mono_field_get_name (&klass->fields [i]) == name)
6946 return &klass->fields [i];
6947 g_assert_not_reached ();
6949 if (klass->field.count) {
6950 if ((idx >= klass->field.first) && (idx < klass->field.first + klass->field.count)){
6951 return &klass->fields [idx - klass->field.first];
6955 klass = klass->parent;
6961 * mono_class_get_field:
6962 * @class: the class to lookup the field.
6963 * @field_token: the field token
6965 * Returns: A MonoClassField representing the type and offset of
6966 * the field, or a NULL value if the field does not belong to this
6970 mono_class_get_field (MonoClass *klass, guint32 field_token)
6972 int idx = mono_metadata_token_index (field_token);
6974 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6976 return mono_class_get_field_idx (klass, idx - 1);
6980 * mono_class_get_field_from_name:
6981 * @klass: the class to lookup the field.
6982 * @name: the field name
6984 * Search the class @klass and it's parents for a field with the name @name.
6986 * Returns: The MonoClassField pointer of the named field or NULL
6989 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6991 return mono_class_get_field_from_name_full (klass, name, NULL);
6995 * mono_class_get_field_from_name_full:
6996 * @klass: the class to lookup the field.
6997 * @name: the field name
6998 * @type: the type of the fields. This optional.
7000 * Search the class @klass and it's parents for a field with the name @name and type @type.
7002 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
7003 * of its generic type definition.
7005 * Returns: The MonoClassField pointer of the named field or NULL
7008 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
7012 mono_class_setup_fields_locking (klass);
7013 if (mono_class_has_failure (klass))
7017 for (i = 0; i < klass->field.count; ++i) {
7018 MonoClassField *field = &klass->fields [i];
7020 if (strcmp (name, mono_field_get_name (field)) != 0)
7024 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
7025 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
7030 klass = klass->parent;
7036 * mono_class_get_field_token:
7037 * @field: the field we need the token of
7039 * Get the token of a field. Note that the tokesn is only valid for the image
7040 * the field was loaded from. Don't use this function for fields in dynamic types.
7042 * Returns: The token representing the field in the image it was loaded from.
7045 mono_class_get_field_token (MonoClassField *field)
7047 MonoClass *klass = field->parent;
7050 mono_class_setup_fields_locking (klass);
7055 for (i = 0; i < klass->field.count; ++i) {
7056 if (&klass->fields [i] == field) {
7057 int idx = klass->field.first + i + 1;
7059 if (klass->image->uncompressed_metadata)
7060 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
7061 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
7064 klass = klass->parent;
7067 g_assert_not_reached ();
7072 mono_field_get_index (MonoClassField *field)
7074 int index = field - field->parent->fields;
7076 g_assert (index >= 0 && index < field->parent->field.count);
7082 * mono_class_get_field_default_value:
7084 * Return the default value of the field as a pointer into the metadata blob.
7087 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
7090 guint32 constant_cols [MONO_CONSTANT_SIZE];
7092 MonoClass *klass = field->parent;
7094 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7096 if (!klass->ext || !klass->ext->field_def_values) {
7097 MonoFieldDefaultValue *def_values;
7099 mono_class_alloc_ext (klass);
7101 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
7103 mono_image_lock (klass->image);
7104 mono_memory_barrier ();
7105 if (!klass->ext->field_def_values)
7106 klass->ext->field_def_values = def_values;
7107 mono_image_unlock (klass->image);
7110 field_index = mono_field_get_index (field);
7112 if (!klass->ext->field_def_values [field_index].data) {
7113 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7117 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7119 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7120 klass->ext->field_def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7121 klass->ext->field_def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7124 *def_type = klass->ext->field_def_values [field_index].def_type;
7125 return klass->ext->field_def_values [field_index].data;
7129 mono_property_get_index (MonoProperty *prop)
7131 int index = prop - prop->parent->ext->properties;
7133 g_assert (index >= 0 && index < prop->parent->ext->property.count);
7139 * mono_class_get_property_default_value:
7141 * Return the default value of the field as a pointer into the metadata blob.
7144 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7147 guint32 constant_cols [MONO_CONSTANT_SIZE];
7148 MonoClass *klass = property->parent;
7150 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7152 * We don't cache here because it is not used by C# so it's quite rare, but
7153 * we still do the lookup in klass->ext because that is where the data
7154 * is stored for dynamic assemblies.
7157 if (image_is_dynamic (klass->image)) {
7158 int prop_index = mono_property_get_index (property);
7159 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
7160 *def_type = klass->ext->prop_def_values [prop_index].def_type;
7161 return klass->ext->prop_def_values [prop_index].data;
7165 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7169 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7170 *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7171 return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7175 mono_class_get_event_token (MonoEvent *event)
7177 MonoClass *klass = event->parent;
7182 for (i = 0; i < klass->ext->event.count; ++i) {
7183 if (&klass->ext->events [i] == event)
7184 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
7187 klass = klass->parent;
7190 g_assert_not_reached ();
7195 * mono_class_get_property_from_name:
7197 * @name: name of the property to lookup in the specified class
7199 * Use this method to lookup a property in a class
7200 * Returns: the MonoProperty with the given name, or NULL if the property
7201 * does not exist on the @klass.
7204 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7208 gpointer iter = NULL;
7209 while ((p = mono_class_get_properties (klass, &iter))) {
7210 if (! strcmp (name, p->name))
7213 klass = klass->parent;
7219 * mono_class_get_property_token:
7220 * @prop: MonoProperty to query
7222 * Returns: The ECMA token for the specified property.
7225 mono_class_get_property_token (MonoProperty *prop)
7227 MonoClass *klass = prop->parent;
7231 gpointer iter = NULL;
7232 while ((p = mono_class_get_properties (klass, &iter))) {
7233 if (&klass->ext->properties [i] == prop)
7234 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
7238 klass = klass->parent;
7241 g_assert_not_reached ();
7246 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7248 const char *name, *nspace;
7249 if (image_is_dynamic (image))
7250 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7252 switch (type_token & 0xff000000){
7253 case MONO_TOKEN_TYPE_DEF: {
7254 guint32 cols [MONO_TYPEDEF_SIZE];
7255 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7256 guint tidx = mono_metadata_token_index (type_token);
7258 if (tidx > tt->rows)
7259 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7261 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7262 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7263 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7264 if (strlen (nspace) == 0)
7265 return g_strdup_printf ("%s", name);
7267 return g_strdup_printf ("%s.%s", nspace, name);
7270 case MONO_TOKEN_TYPE_REF: {
7272 guint32 cols [MONO_TYPEREF_SIZE];
7273 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7274 guint tidx = mono_metadata_token_index (type_token);
7277 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7279 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7280 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7281 mono_error_cleanup (&error);
7285 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7286 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7287 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7288 if (strlen (nspace) == 0)
7289 return g_strdup_printf ("%s", name);
7291 return g_strdup_printf ("%s.%s", nspace, name);
7294 case MONO_TOKEN_TYPE_SPEC:
7295 return g_strdup_printf ("Typespec 0x%08x", type_token);
7297 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7302 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7304 if (image_is_dynamic (image))
7305 return g_strdup_printf ("DynamicAssembly %s", image->name);
7307 switch (type_token & 0xff000000){
7308 case MONO_TOKEN_TYPE_DEF:
7309 if (image->assembly)
7310 return mono_stringify_assembly_name (&image->assembly->aname);
7311 else if (image->assembly_name)
7312 return g_strdup (image->assembly_name);
7313 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7314 case MONO_TOKEN_TYPE_REF: {
7316 MonoAssemblyName aname;
7317 guint32 cols [MONO_TYPEREF_SIZE];
7318 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7319 guint32 idx = mono_metadata_token_index (type_token);
7322 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7324 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7325 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7326 mono_error_cleanup (&error);
7329 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7331 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7332 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7333 case MONO_RESOLUTION_SCOPE_MODULE:
7335 return g_strdup ("");
7336 case MONO_RESOLUTION_SCOPE_MODULEREF:
7338 return g_strdup ("");
7339 case MONO_RESOLUTION_SCOPE_TYPEREF:
7341 return g_strdup ("");
7342 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7343 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7344 return mono_stringify_assembly_name (&aname);
7346 g_assert_not_reached ();
7350 case MONO_TOKEN_TYPE_SPEC:
7352 return g_strdup ("");
7354 g_assert_not_reached ();
7361 * mono_class_get_full:
7362 * @image: the image where the class resides
7363 * @type_token: the token for the class
7364 * @context: the generic context used to evaluate generic instantiations in
7365 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7367 * Returns: The MonoClass that represents @type_token in @image
7370 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7374 klass = mono_class_get_checked (image, type_token, &error);
7376 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7377 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7379 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7385 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7389 mono_error_init (error);
7390 klass = mono_class_get_checked (image, type_token, error);
7392 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7393 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7398 * mono_class_get_checked:
7399 * @image: the image where the class resides
7400 * @type_token: the token for the class
7401 * @error: error object to return any error
7403 * Returns: The MonoClass that represents @type_token in @image, or NULL on error.
7406 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7408 MonoClass *klass = NULL;
7410 mono_error_init (error);
7412 if (image_is_dynamic (image)) {
7413 int table = mono_metadata_token_table (type_token);
7415 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7416 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7419 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
7423 switch (type_token & 0xff000000){
7424 case MONO_TOKEN_TYPE_DEF:
7425 klass = mono_class_create_from_typedef (image, type_token, error);
7427 case MONO_TOKEN_TYPE_REF:
7428 klass = mono_class_from_typeref_checked (image, type_token, error);
7430 case MONO_TOKEN_TYPE_SPEC:
7431 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7434 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7438 /* Generic case, should be avoided for when a better error is possible. */
7439 if (!klass && mono_error_ok (error)) {
7440 char *name = mono_class_name_from_token (image, type_token);
7441 char *assembly = mono_assembly_name_from_token (image, type_token);
7442 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7450 * mono_type_get_checked:
7451 * @image: the image where the type resides
7452 * @type_token: the token for the type
7453 * @context: the generic context used to evaluate generic instantiations in
7454 * @error: Error handling context
7456 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7458 * Returns: The MonoType that represents @type_token in @image
7461 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7463 MonoType *type = NULL;
7464 gboolean inflated = FALSE;
7466 mono_error_init (error);
7468 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7469 if (image_is_dynamic (image)) {
7470 MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
7471 return_val_if_nok (error, NULL);
7472 return mono_class_get_type (klass);
7475 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7476 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7483 return mono_class_get_type (klass);
7486 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7493 MonoType *tmp = type;
7494 type = mono_class_get_type (mono_class_from_mono_type (type));
7495 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7496 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7497 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7499 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7501 if (type->type != tmp->type)
7504 mono_metadata_free_type (tmp);
7511 * @image: image where the class token will be looked up.
7512 * @type_token: a type token from the image
7514 * Returns the MonoClass with the given @type_token on the @image
7517 mono_class_get (MonoImage *image, guint32 type_token)
7519 return mono_class_get_full (image, type_token, NULL);
7523 * mono_image_init_name_cache:
7525 * Initializes the class name cache stored in image->name_cache.
7527 * LOCKING: Acquires the corresponding image lock.
7530 mono_image_init_name_cache (MonoImage *image)
7532 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7533 guint32 cols [MONO_TYPEDEF_SIZE];
7536 guint32 i, visib, nspace_index;
7537 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7539 if (image->name_cache)
7542 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7544 if (image_is_dynamic (image)) {
7545 mono_image_lock (image);
7546 if (image->name_cache) {
7547 /* Somebody initialized it before us */
7548 g_hash_table_destroy (the_name_cache);
7550 mono_atomic_store_release (&image->name_cache, the_name_cache);
7552 mono_image_unlock (image);
7556 /* Temporary hash table to avoid lookups in the nspace_table */
7557 name_cache2 = g_hash_table_new (NULL, NULL);
7559 for (i = 1; i <= t->rows; ++i) {
7560 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7561 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7563 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7564 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7566 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7568 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7569 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7571 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7572 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7573 if (!nspace_table) {
7574 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7575 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7576 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7579 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7582 /* Load type names from EXPORTEDTYPES table */
7584 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7585 guint32 cols [MONO_EXP_TYPE_SIZE];
7588 for (i = 0; i < t->rows; ++i) {
7589 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7591 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7592 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7596 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7597 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7599 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7600 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7601 if (!nspace_table) {
7602 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7603 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7604 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7607 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7611 g_hash_table_destroy (name_cache2);
7613 mono_image_lock (image);
7614 if (image->name_cache) {
7615 /* Somebody initialized it before us */
7616 g_hash_table_destroy (the_name_cache);
7618 mono_atomic_store_release (&image->name_cache, the_name_cache);
7620 mono_image_unlock (image);
7623 /*FIXME Only dynamic assemblies should allow this operation.*/
7625 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7626 const char *name, guint32 index)
7628 GHashTable *nspace_table;
7629 GHashTable *name_cache;
7632 mono_image_init_name_cache (image);
7633 mono_image_lock (image);
7635 name_cache = image->name_cache;
7636 if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7637 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7638 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7641 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7642 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7644 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7646 mono_image_unlock (image);
7655 find_nocase (gpointer key, gpointer value, gpointer user_data)
7657 char *name = (char*)key;
7658 FindUserData *data = (FindUserData*)user_data;
7660 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7661 data->value = value;
7665 * mono_class_from_name_case:
7666 * @image: The MonoImage where the type is looked up in
7667 * @name_space: the type namespace
7668 * @name: the type short name.
7669 * @deprecated: use the mono_class_from_name_case_checked variant instead.
7671 * Obtains a MonoClass with a given namespace and a given name which
7672 * is located in the given MonoImage. The namespace and name
7673 * lookups are case insensitive.
7676 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7679 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7680 mono_error_cleanup (&error);
7686 * mono_class_from_name_case:
7687 * @image: The MonoImage where the type is looked up in
7688 * @name_space: the type namespace
7689 * @name: the type short name.
7692 * Obtains a MonoClass with a given namespace and a given name which
7693 * is located in the given MonoImage. The namespace and name
7694 * lookups are case insensitive.
7696 * Returns: The MonoClass if the given namespace and name were found, or NULL if it
7697 * was not found. The @error object will contain information about the problem
7701 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7703 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7704 guint32 cols [MONO_TYPEDEF_SIZE];
7709 mono_error_init (error);
7711 if (image_is_dynamic (image)) {
7713 FindUserData user_data;
7715 mono_image_init_name_cache (image);
7716 mono_image_lock (image);
7718 user_data.key = name_space;
7719 user_data.value = NULL;
7720 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7722 if (user_data.value) {
7723 GHashTable *nspace_table = (GHashTable*)user_data.value;
7725 user_data.key = name;
7726 user_data.value = NULL;
7728 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7730 if (user_data.value)
7731 token = GPOINTER_TO_UINT (user_data.value);
7734 mono_image_unlock (image);
7737 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7743 /* add a cache if needed */
7744 for (i = 1; i <= t->rows; ++i) {
7745 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7746 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7748 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7749 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7751 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7753 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7754 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7755 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7756 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7762 return_nested_in (MonoClass *klass, char *nested)
7765 char *s = strchr (nested, '/');
7766 gpointer iter = NULL;
7773 while ((found = mono_class_get_nested_types (klass, &iter))) {
7774 if (strcmp (found->name, nested) == 0) {
7776 return return_nested_in (found, s);
7784 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7786 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7787 MonoImage *file_image;
7791 mono_error_init (error);
7794 * The EXPORTEDTYPES table only contains public types, so have to search the
7796 * Note: image->modules contains the contents of the MODULEREF table, while
7797 * the real module list is in the FILE table.
7799 for (i = 0; i < file_table->rows; i++) {
7800 guint32 cols [MONO_FILE_SIZE];
7801 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7802 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7805 file_image = mono_image_load_file_for_image_checked (image, i + 1, error);
7807 klass = mono_class_from_name_checked (file_image, name_space, name, error);
7808 if (klass || !is_ok (error))
7817 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7819 GHashTable *nspace_table;
7820 MonoImage *loaded_image;
7827 mono_error_init (error);
7829 // Checking visited images avoids stack overflows when cyclic references exist.
7830 if (g_hash_table_lookup (visited_images, image))
7833 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7835 if ((nested = strchr (name, '/'))) {
7836 int pos = nested - name;
7837 int len = strlen (name);
7840 memcpy (buf, name, len + 1);
7842 nested = buf + pos + 1;
7846 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7847 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7848 gboolean res = get_class_from_name (image, name_space, name, &klass);
7851 klass = search_modules (image, name_space, name, error);
7856 return klass ? return_nested_in (klass, nested) : NULL;
7862 mono_image_init_name_cache (image);
7863 mono_image_lock (image);
7865 nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7868 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7870 mono_image_unlock (image);
7872 if (!token && image_is_dynamic (image) && image->modules) {
7873 /* Search modules as well */
7874 for (i = 0; i < image->module_count; ++i) {
7875 MonoImage *module = image->modules [i];
7877 klass = mono_class_from_name_checked (module, name_space, name, error);
7878 if (klass || !is_ok (error))
7884 klass = search_modules (image, name_space, name, error);
7885 if (klass || !is_ok (error))
7890 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7891 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7892 guint32 cols [MONO_EXP_TYPE_SIZE];
7895 idx = mono_metadata_token_index (token);
7897 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7899 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7900 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7901 loaded_image = mono_assembly_load_module_checked (image->assembly, impl >> MONO_IMPLEMENTATION_BITS, error);
7904 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7906 return klass ? return_nested_in (klass, nested) : NULL;
7908 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7909 guint32 assembly_idx;
7911 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7913 mono_assembly_load_reference (image, assembly_idx - 1);
7914 g_assert (image->references [assembly_idx - 1]);
7915 if (image->references [assembly_idx - 1] == (gpointer)-1)
7917 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
7919 return klass ? return_nested_in (klass, nested) : NULL;
7922 g_assert_not_reached ();
7926 token = MONO_TOKEN_TYPE_DEF | token;
7928 klass = mono_class_get_checked (image, token, error);
7930 return return_nested_in (klass, nested);
7935 * mono_class_from_name_checked:
7936 * @image: The MonoImage where the type is looked up in
7937 * @name_space: the type namespace
7938 * @name: the type short name.
7940 * Obtains a MonoClass with a given namespace and a given name which
7941 * is located in the given MonoImage.
7943 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
7944 * set if the class was not found or it will return NULL and set the error if there was a loading error.
7947 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7950 GHashTable *visited_images;
7952 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7954 klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
7956 g_hash_table_destroy (visited_images);
7962 * mono_class_from_name:
7963 * @image: The MonoImage where the type is looked up in
7964 * @name_space: the type namespace
7965 * @name: the type short name.
7967 * Obtains a MonoClass with a given namespace and a given name which
7968 * is located in the given MonoImage.
7970 * To reference nested classes, use the "/" character as a separator.
7971 * For example use "Foo/Bar" to reference the class Bar that is nested
7972 * inside Foo, like this: "class Foo { class Bar {} }".
7975 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7980 klass = mono_class_from_name_checked (image, name_space, name, &error);
7981 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
7987 * mono_class_load_from_name:
7988 * @image: The MonoImage where the type is looked up in
7989 * @name_space: the type namespace
7990 * @name: the type short name.
7992 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
7993 * This function should be used by the runtime for critical types to which there's no way to recover but crash
7994 * If they are missing. Thing of System.Object or System.String.
7997 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
8002 klass = mono_class_from_name_checked (image, name_space, name, &error);
8004 g_error ("Runtime critical type %s.%s not found", name_space, name);
8005 if (!mono_error_ok (&error))
8006 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8011 * mono_class_try_load_from_name:
8012 * @image: The MonoImage where the type is looked up in
8013 * @name_space: the type namespace
8014 * @name: the type short name.
8016 * This function tries to load a type, returning the class was found or NULL otherwise.
8017 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
8019 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
8020 * a type that we would otherwise assume to be available but was not due some error.
8024 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
8029 klass = mono_class_from_name_checked (image, name_space, name, &error);
8030 if (!mono_error_ok (&error))
8031 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8037 * mono_class_is_subclass_of:
8038 * @klass: class to probe if it is a subclass of another one
8039 * @klassc: the class we suspect is the base class
8040 * @check_interfaces: whether we should perform interface checks
8042 * This method determines whether @klass is a subclass of @klassc.
8044 * If the @check_interfaces flag is set, then if @klassc is an interface
8045 * this method return TRUE if the @klass implements the interface or
8046 * if @klass is an interface, if one of its base classes is @klass.
8048 * If @check_interfaces is false then, then if @klass is not an interface
8049 * then it returns TRUE if the @klass is a subclass of @klassc.
8051 * if @klass is an interface and @klassc is System.Object, then this function
8056 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
8057 gboolean check_interfaces)
8059 /* FIXME test for interfaces with variant generic arguments */
8060 mono_class_init (klass);
8061 mono_class_init (klassc);
8063 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
8064 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
8066 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
8069 for (i = 0; i < klass->interface_count; i ++) {
8070 MonoClass *ic = klass->interfaces [i];
8075 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
8080 * MS.NET thinks interfaces are a subclass of Object, so we think it as
8083 if (klassc == mono_defaults.object_class)
8090 mono_type_is_generic_argument (MonoType *type)
8092 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
8096 mono_class_has_variant_generic_params (MonoClass *klass)
8099 MonoGenericContainer *container;
8101 if (!klass->generic_class)
8104 container = klass->generic_class->container_class->generic_container;
8106 for (i = 0; i < container->type_argc; ++i)
8107 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8114 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8116 if (target == candidate)
8119 if (check_for_reference_conv &&
8120 mono_type_is_generic_argument (&target->byval_arg) &&
8121 mono_type_is_generic_argument (&candidate->byval_arg)) {
8122 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8123 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8125 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8128 if (!mono_class_is_assignable_from (target, candidate))
8134 * @container the generic container from the GTD
8135 * @klass: the class to be assigned to
8136 * @oklass: the source class
8138 * Both @klass and @oklass must be instances of the same generic interface.
8140 * Returns: TRUE if @klass can be assigned to a @klass variable
8143 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8146 MonoType **klass_argv, **oklass_argv;
8147 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8148 MonoGenericContainer *container = klass_gtd->generic_container;
8150 if (klass == oklass)
8153 /*Viable candidates are instances of the same generic interface*/
8154 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8157 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8158 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8160 for (j = 0; j < container->type_argc; ++j) {
8161 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8162 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8164 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8168 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8169 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8171 if (param1_class != param2_class) {
8172 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8173 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8175 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8176 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8186 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8188 MonoGenericParam *gparam, *ogparam;
8189 MonoGenericParamInfo *tinfo, *cinfo;
8190 MonoClass **candidate_class;
8191 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8194 if (target == candidate)
8196 if (target->byval_arg.type != candidate->byval_arg.type)
8199 gparam = target->byval_arg.data.generic_param;
8200 ogparam = candidate->byval_arg.data.generic_param;
8201 tinfo = mono_generic_param_info (gparam);
8202 cinfo = mono_generic_param_info (ogparam);
8204 class_constraint_satisfied = FALSE;
8205 valuetype_constraint_satisfied = FALSE;
8207 /*candidate must have a super set of target's special constraints*/
8208 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8209 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8211 if (cinfo->constraints) {
8212 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8213 MonoClass *cc = *candidate_class;
8215 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8216 class_constraint_satisfied = TRUE;
8217 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8218 valuetype_constraint_satisfied = TRUE;
8221 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8222 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8224 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8226 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8228 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8229 valuetype_constraint_satisfied)) {
8234 /*candidate type constraints must be a superset of target's*/
8235 if (tinfo->constraints) {
8236 MonoClass **target_class;
8237 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8238 MonoClass *tc = *target_class;
8241 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8242 * check it's constraints since it satisfy the constraint by itself.
8244 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8247 if (!cinfo->constraints)
8250 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8251 MonoClass *cc = *candidate_class;
8253 if (mono_class_is_assignable_from (tc, cc))
8257 * This happens when we have the following:
8259 * Bar<K> where K : IFace
8260 * Foo<T, U> where T : U where U : IFace
8262 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8265 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8266 if (mono_gparam_is_assignable_from (target, cc))
8270 if (!*candidate_class)
8275 /*candidate itself must have a constraint that satisfy target*/
8276 if (cinfo->constraints) {
8277 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8278 MonoClass *cc = *candidate_class;
8279 if (mono_class_is_assignable_from (target, cc))
8287 * mono_class_is_assignable_from:
8288 * @klass: the class to be assigned to
8289 * @oklass: the source class
8291 * Returns: TRUE if an instance of object oklass can be assigned to an
8292 * instance of object @klass
8295 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8298 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8300 mono_class_init (klass);
8302 if (!oklass->inited)
8303 mono_class_init (oklass);
8305 if (mono_class_has_failure (klass) || mono_class_has_failure (oklass))
8308 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8309 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8311 return mono_gparam_is_assignable_from (klass, oklass);
8314 if (MONO_CLASS_IS_INTERFACE (klass)) {
8315 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8316 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8317 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8321 for (i = 0; constraints [i]; ++i) {
8322 if (mono_class_is_assignable_from (klass, constraints [i]))
8330 /* interface_offsets might not be set for dynamic classes */
8331 if (oklass->ref_info_handle && !oklass->interface_bitmap) {
8333 * oklass might be a generic type parameter but they have
8334 * interface_offsets set.
8336 gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8337 if (!is_ok (&error)) {
8338 mono_error_cleanup (&error);
8343 if (!oklass->interface_bitmap)
8344 /* Happens with generic instances of not-yet created dynamic types */
8346 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8349 if (mono_class_has_variant_generic_params (klass)) {
8351 mono_class_setup_interfaces (oklass, &error);
8352 if (!mono_error_ok (&error)) {
8353 mono_error_cleanup (&error);
8357 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8358 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8359 MonoClass *iface = oklass->interfaces_packed [i];
8361 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8366 } else if (klass->delegate) {
8367 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8369 }else if (klass->rank) {
8370 MonoClass *eclass, *eoclass;
8372 if (oklass->rank != klass->rank)
8375 /* vectors vs. one dimensional arrays */
8376 if (oklass->byval_arg.type != klass->byval_arg.type)
8379 eclass = klass->cast_class;
8380 eoclass = oklass->cast_class;
8383 * a is b does not imply a[] is b[] when a is a valuetype, and
8384 * b is a reference type.
8387 if (eoclass->valuetype) {
8388 if ((eclass == mono_defaults.enum_class) ||
8389 (eclass == mono_defaults.enum_class->parent) ||
8390 (eclass == mono_defaults.object_class))
8394 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8395 } else if (mono_class_is_nullable (klass)) {
8396 if (mono_class_is_nullable (oklass))
8397 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8399 return mono_class_is_assignable_from (klass->cast_class, oklass);
8400 } else if (klass == mono_defaults.object_class)
8403 return mono_class_has_parent (oklass, klass);
8406 /*Check if @oklass is variant compatible with @klass.*/
8408 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8411 MonoType **klass_argv, **oklass_argv;
8412 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8413 MonoGenericContainer *container = klass_gtd->generic_container;
8415 /*Viable candidates are instances of the same generic interface*/
8416 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8419 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8420 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8422 for (j = 0; j < container->type_argc; ++j) {
8423 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8424 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8426 if (param1_class->valuetype != param2_class->valuetype)
8430 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8431 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8433 if (param1_class != param2_class) {
8434 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8435 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8437 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8438 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8446 /*Check if @candidate implements the interface @target*/
8448 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8452 gboolean is_variant = mono_class_has_variant_generic_params (target);
8454 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8455 if (mono_class_is_variant_compatible_slow (target, candidate))
8460 if (candidate == target)
8463 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8464 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8465 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (candidate);
8467 if (tb && tb->interfaces) {
8468 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8469 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8470 MonoClass *iface_class;
8472 /* we can't realize the type here since it can do pretty much anything. */
8475 iface_class = mono_class_from_mono_type (iface->type);
8476 if (iface_class == target)
8478 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8480 if (mono_class_implement_interface_slow (target, iface_class))
8485 /*setup_interfaces don't mono_class_init anything*/
8486 /*FIXME this doesn't handle primitive type arrays.
8487 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8488 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8490 mono_class_setup_interfaces (candidate, &error);
8491 if (!mono_error_ok (&error)) {
8492 mono_error_cleanup (&error);
8496 for (i = 0; i < candidate->interface_count; ++i) {
8497 if (candidate->interfaces [i] == target)
8500 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8503 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8507 candidate = candidate->parent;
8508 } while (candidate);
8514 * Check if @oklass can be assigned to @klass.
8515 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8518 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8520 if (candidate == target)
8522 if (target == mono_defaults.object_class)
8525 if (mono_class_has_parent (candidate, target))
8528 /*If target is not an interface there is no need to check them.*/
8529 if (MONO_CLASS_IS_INTERFACE (target))
8530 return mono_class_implement_interface_slow (target, candidate);
8532 if (target->delegate && mono_class_has_variant_generic_params (target))
8533 return mono_class_is_variant_compatible (target, candidate, FALSE);
8536 MonoClass *eclass, *eoclass;
8538 if (target->rank != candidate->rank)
8541 /* vectors vs. one dimensional arrays */
8542 if (target->byval_arg.type != candidate->byval_arg.type)
8545 eclass = target->cast_class;
8546 eoclass = candidate->cast_class;
8549 * a is b does not imply a[] is b[] when a is a valuetype, and
8550 * b is a reference type.
8553 if (eoclass->valuetype) {
8554 if ((eclass == mono_defaults.enum_class) ||
8555 (eclass == mono_defaults.enum_class->parent) ||
8556 (eclass == mono_defaults.object_class))
8560 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8562 /*FIXME properly handle nullables */
8563 /*FIXME properly handle (M)VAR */
8568 * mono_class_get_cctor:
8569 * @klass: A MonoClass pointer
8571 * Returns: The static constructor of @klass if it exists, NULL otherwise.
8574 mono_class_get_cctor (MonoClass *klass)
8576 MonoCachedClassInfo cached_info;
8578 if (image_is_dynamic (klass->image)) {
8580 * has_cctor is not set for these classes because mono_class_init () is
8583 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8586 if (!klass->has_cctor)
8589 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8591 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8592 if (!mono_error_ok (&error))
8593 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8597 if (klass->generic_class && !klass->methods)
8598 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8600 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8604 * mono_class_get_finalizer:
8605 * @klass: The MonoClass pointer
8607 * Returns: The finalizer method of @klass if it exists, NULL otherwise.
8610 mono_class_get_finalizer (MonoClass *klass)
8612 MonoCachedClassInfo cached_info;
8615 mono_class_init (klass);
8616 if (!mono_class_has_finalizer (klass))
8619 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8621 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8622 if (!mono_error_ok (&error))
8623 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8626 mono_class_setup_vtable (klass);
8627 return klass->vtable [finalize_slot];
8632 * mono_class_needs_cctor_run:
8633 * @klass: the MonoClass pointer
8634 * @caller: a MonoMethod describing the caller
8636 * Determines whenever the class has a static constructor and whenever it
8637 * needs to be called when executing CALLER.
8640 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8644 method = mono_class_get_cctor (klass);
8646 return (method == caller) ? FALSE : TRUE;
8652 * mono_class_array_element_size:
8655 * Returns: The number of bytes an element of type @klass
8656 * uses when stored into an array.
8659 mono_class_array_element_size (MonoClass *klass)
8661 MonoType *type = &klass->byval_arg;
8664 switch (type->type) {
8667 case MONO_TYPE_BOOLEAN:
8671 case MONO_TYPE_CHAR:
8680 case MONO_TYPE_CLASS:
8681 case MONO_TYPE_STRING:
8682 case MONO_TYPE_OBJECT:
8683 case MONO_TYPE_SZARRAY:
8684 case MONO_TYPE_ARRAY:
8685 return sizeof (gpointer);
8690 case MONO_TYPE_VALUETYPE:
8691 if (type->data.klass->enumtype) {
8692 type = mono_class_enum_basetype (type->data.klass);
8693 klass = klass->element_class;
8696 return mono_class_instance_size (klass) - sizeof (MonoObject);
8697 case MONO_TYPE_GENERICINST:
8698 type = &type->data.generic_class->container_class->byval_arg;
8701 case MONO_TYPE_MVAR: {
8704 return mono_type_size (type, &align);
8706 case MONO_TYPE_VOID:
8710 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8716 * mono_array_element_size:
8717 * @ac: pointer to a #MonoArrayClass
8719 * Returns: The size of single array element.
8722 mono_array_element_size (MonoClass *ac)
8724 g_assert (ac->rank);
8725 return ac->sizes.element_size;
8729 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8730 MonoGenericContext *context)
8733 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8734 g_assert (mono_error_ok (&error));
8739 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8740 MonoGenericContext *context, MonoError *error)
8742 mono_error_init (error);
8744 if (image_is_dynamic (image)) {
8745 MonoClass *tmp_handle_class;
8746 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
8748 mono_error_assert_ok (error);
8749 g_assert (tmp_handle_class);
8751 *handle_class = tmp_handle_class;
8753 if (tmp_handle_class == mono_defaults.typehandle_class)
8754 return &((MonoClass*)obj)->byval_arg;
8759 switch (token & 0xff000000) {
8760 case MONO_TOKEN_TYPE_DEF:
8761 case MONO_TOKEN_TYPE_REF:
8762 case MONO_TOKEN_TYPE_SPEC: {
8765 *handle_class = mono_defaults.typehandle_class;
8766 type = mono_type_get_checked (image, token, context, error);
8770 mono_class_init (mono_class_from_mono_type (type));
8771 /* We return a MonoType* as handle */
8774 case MONO_TOKEN_FIELD_DEF: {
8776 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8778 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8782 *handle_class = mono_defaults.fieldhandle_class;
8783 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8787 mono_class_init (klass);
8788 return mono_class_get_field (klass, token);
8790 case MONO_TOKEN_METHOD_DEF:
8791 case MONO_TOKEN_METHOD_SPEC: {
8793 meth = mono_get_method_checked (image, token, NULL, context, error);
8795 *handle_class = mono_defaults.methodhandle_class;
8801 case MONO_TOKEN_MEMBER_REF: {
8802 guint32 cols [MONO_MEMBERREF_SIZE];
8804 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8805 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8806 mono_metadata_decode_blob_size (sig, &sig);
8807 if (*sig == 0x6) { /* it's a field */
8809 MonoClassField *field;
8810 field = mono_field_from_token_checked (image, token, &klass, context, error);
8812 *handle_class = mono_defaults.fieldhandle_class;
8816 meth = mono_get_method_checked (image, token, NULL, context, error);
8818 *handle_class = mono_defaults.methodhandle_class;
8823 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8829 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
8831 MonoClass *handle_class;
8832 mono_error_init (error);
8833 return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
8837 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
8839 return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
8842 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8845 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8847 get_cached_class_info = func;
8851 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8853 if (!get_cached_class_info)
8856 return get_cached_class_info (klass, res);
8860 mono_install_get_class_from_name (MonoGetClassFromName func)
8862 get_class_from_name = func;
8866 * mono_class_get_image:
8868 * Use this method to get the `MonoImage*` where this class came from.
8870 * Returns: The image where this class is defined.
8873 mono_class_get_image (MonoClass *klass)
8875 return klass->image;
8879 * mono_class_get_element_class:
8880 * @klass: the MonoClass to act on
8882 * Use this function to get the element class of an array.
8884 * Returns: The element class of an array.
8887 mono_class_get_element_class (MonoClass *klass)
8889 return klass->element_class;
8893 * mono_class_is_valuetype:
8894 * @klass: the MonoClass to act on
8896 * Use this method to determine if the provided `MonoClass*` represents a value type,
8897 * or a reference type.
8899 * Returns: TRUE if the MonoClass represents a ValueType, FALSE if it represents a reference type.
8902 mono_class_is_valuetype (MonoClass *klass)
8904 return klass->valuetype;
8908 * mono_class_is_enum:
8909 * @klass: the MonoClass to act on
8911 * Use this function to determine if the provided `MonoClass*` represents an enumeration.
8913 * Returns: TRUE if the MonoClass represents an enumeration.
8916 mono_class_is_enum (MonoClass *klass)
8918 return klass->enumtype;
8922 * mono_class_enum_basetype:
8923 * @klass: the MonoClass to act on
8925 * Use this function to get the underlying type for an enumeration value.
8927 * Returns: The underlying type representation for an enumeration.
8930 mono_class_enum_basetype (MonoClass *klass)
8932 if (klass->element_class == klass)
8933 /* SRE or broken types */
8936 return &klass->element_class->byval_arg;
8940 * mono_class_get_parent
8941 * @klass: the MonoClass to act on
8943 * Returns: The parent class for this class.
8946 mono_class_get_parent (MonoClass *klass)
8948 return klass->parent;
8952 * mono_class_get_nesting_type:
8953 * @klass: the MonoClass to act on
8955 * Use this function to obtain the class that the provided `MonoClass*` is nested on.
8957 * If the return is NULL, this indicates that this class is not nested.
8959 * Returns: The container type where this type is nested or NULL if this type is not a nested type.
8962 mono_class_get_nesting_type (MonoClass *klass)
8964 return klass->nested_in;
8968 * mono_class_get_rank:
8969 * @klass: the MonoClass to act on
8971 * Returns: The rank for the array (the number of dimensions).
8974 mono_class_get_rank (MonoClass *klass)
8980 * mono_class_get_flags:
8981 * @klass: the MonoClass to act on
8983 * The type flags from the TypeDef table from the metadata.
8984 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8987 * Returns: The flags from the TypeDef table.
8990 mono_class_get_flags (MonoClass *klass)
8992 return klass->flags;
8996 * mono_class_get_name
8997 * @klass: the MonoClass to act on
8999 * Returns: The name of the class.
9002 mono_class_get_name (MonoClass *klass)
9008 * mono_class_get_namespace:
9009 * @klass: the MonoClass to act on
9011 * Returns: The namespace of the class.
9014 mono_class_get_namespace (MonoClass *klass)
9016 return klass->name_space;
9020 * mono_class_get_type:
9021 * @klass: the MonoClass to act on
9023 * This method returns the internal Type representation for the class.
9025 * Returns: The MonoType from the class.
9028 mono_class_get_type (MonoClass *klass)
9030 return &klass->byval_arg;
9034 * mono_class_get_type_token:
9035 * @klass: the MonoClass to act on
9037 * This method returns type token for the class.
9039 * Returns: The type token for the class.
9042 mono_class_get_type_token (MonoClass *klass)
9044 return klass->type_token;
9048 * mono_class_get_byref_type:
9049 * @klass: the MonoClass to act on
9054 mono_class_get_byref_type (MonoClass *klass)
9056 return &klass->this_arg;
9060 * mono_class_num_fields:
9061 * @klass: the MonoClass to act on
9063 * Returns: The number of static and instance fields in the class.
9066 mono_class_num_fields (MonoClass *klass)
9068 return klass->field.count;
9072 * mono_class_num_methods:
9073 * @klass: the MonoClass to act on
9075 * Returns: The number of methods in the class.
9078 mono_class_num_methods (MonoClass *klass)
9080 return klass->method.count;
9084 * mono_class_num_properties
9085 * @klass: the MonoClass to act on
9087 * Returns: The number of properties in the class.
9090 mono_class_num_properties (MonoClass *klass)
9092 mono_class_setup_properties (klass);
9094 return klass->ext->property.count;
9098 * mono_class_num_events:
9099 * @klass: the MonoClass to act on
9101 * Returns: The number of events in the class.
9104 mono_class_num_events (MonoClass *klass)
9106 mono_class_setup_events (klass);
9108 return klass->ext->event.count;
9112 * mono_class_get_fields:
9113 * @klass: the MonoClass to act on
9115 * This routine is an iterator routine for retrieving the fields in a class.
9117 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9118 * iterate over all of the elements. When no more values are
9119 * available, the return value is NULL.
9121 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
9124 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9126 MonoClassField* field;
9130 mono_class_setup_fields_locking (klass);
9131 if (mono_class_has_failure (klass))
9133 /* start from the first */
9134 if (klass->field.count) {
9135 *iter = &klass->fields [0];
9136 return &klass->fields [0];
9142 field = (MonoClassField *)*iter;
9144 if (field < &klass->fields [klass->field.count]) {
9152 * mono_class_get_methods
9153 * @klass: the MonoClass to act on
9155 * This routine is an iterator routine for retrieving the fields in a class.
9157 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9158 * iterate over all of the elements. When no more values are
9159 * available, the return value is NULL.
9161 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
9164 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9166 MonoMethod** method;
9170 mono_class_setup_methods (klass);
9173 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9174 * FIXME we should better report this error to the caller
9176 if (!klass->methods)
9178 /* start from the first */
9179 if (klass->method.count) {
9180 *iter = &klass->methods [0];
9181 return klass->methods [0];
9187 method = (MonoMethod **)*iter;
9189 if (method < &klass->methods [klass->method.count]) {
9197 * mono_class_get_virtual_methods:
9199 * Iterate over the virtual methods of KLASS.
9201 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9204 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9206 MonoMethod** method;
9209 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9211 mono_class_setup_methods (klass);
9213 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9214 * FIXME we should better report this error to the caller
9216 if (!klass->methods)
9218 /* start from the first */
9219 method = &klass->methods [0];
9221 method = (MonoMethod **)*iter;
9224 while (method < &klass->methods [klass->method.count]) {
9225 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9229 if (method < &klass->methods [klass->method.count]) {
9236 /* Search directly in metadata to avoid calling setup_methods () */
9237 MonoMethod *res = NULL;
9243 start_index = GPOINTER_TO_UINT (*iter);
9246 for (i = start_index; i < klass->method.count; ++i) {
9249 /* klass->method.first points into the methodptr table */
9250 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
9252 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9256 if (i < klass->method.count) {
9258 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9259 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9261 /* Add 1 here so the if (*iter) check fails */
9262 *iter = GUINT_TO_POINTER (i + 1);
9271 * mono_class_get_properties:
9272 * @klass: the MonoClass to act on
9274 * This routine is an iterator routine for retrieving the properties in a class.
9276 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9277 * iterate over all of the elements. When no more values are
9278 * available, the return value is NULL.
9280 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9283 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9285 MonoProperty* property;
9289 mono_class_setup_properties (klass);
9290 /* start from the first */
9291 if (klass->ext->property.count) {
9292 *iter = &klass->ext->properties [0];
9293 return (MonoProperty *)*iter;
9299 property = (MonoProperty *)*iter;
9301 if (property < &klass->ext->properties [klass->ext->property.count]) {
9303 return (MonoProperty *)*iter;
9309 * mono_class_get_events:
9310 * @klass: the MonoClass to act on
9312 * This routine is an iterator routine for retrieving the properties in a class.
9314 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9315 * iterate over all of the elements. When no more values are
9316 * available, the return value is NULL.
9318 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9321 mono_class_get_events (MonoClass* klass, gpointer *iter)
9327 mono_class_setup_events (klass);
9328 /* start from the first */
9329 if (klass->ext->event.count) {
9330 *iter = &klass->ext->events [0];
9331 return (MonoEvent *)*iter;
9337 event = (MonoEvent *)*iter;
9339 if (event < &klass->ext->events [klass->ext->event.count]) {
9341 return (MonoEvent *)*iter;
9347 * mono_class_get_interfaces
9348 * @klass: the MonoClass to act on
9350 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9352 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9353 * iterate over all of the elements. When no more values are
9354 * available, the return value is NULL.
9356 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9359 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9367 mono_class_init (klass);
9368 if (!klass->interfaces_inited) {
9369 mono_class_setup_interfaces (klass, &error);
9370 if (!mono_error_ok (&error)) {
9371 mono_error_cleanup (&error);
9375 /* start from the first */
9376 if (klass->interface_count) {
9377 *iter = &klass->interfaces [0];
9378 return klass->interfaces [0];
9384 iface = (MonoClass **)*iter;
9386 if (iface < &klass->interfaces [klass->interface_count]) {
9394 setup_nested_types (MonoClass *klass)
9397 GList *classes, *nested_classes, *l;
9400 if (klass->nested_classes_inited)
9403 if (!klass->type_token)
9404 klass->nested_classes_inited = TRUE;
9406 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9410 guint32 cols [MONO_NESTED_CLASS_SIZE];
9411 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9412 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9413 if (!mono_error_ok (&error)) {
9414 /*FIXME don't swallow the error message*/
9415 mono_error_cleanup (&error);
9417 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9421 classes = g_list_prepend (classes, nclass);
9423 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9426 mono_class_alloc_ext (klass);
9428 nested_classes = NULL;
9429 for (l = classes; l; l = l->next)
9430 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9431 g_list_free (classes);
9433 mono_image_lock (klass->image);
9435 mono_memory_barrier ();
9436 if (!klass->nested_classes_inited) {
9437 klass->ext->nested_classes = nested_classes;
9438 mono_memory_barrier ();
9439 klass->nested_classes_inited = TRUE;
9442 mono_image_unlock (klass->image);
9446 * mono_class_get_nested_types
9447 * @klass: the MonoClass to act on
9449 * This routine is an iterator routine for retrieving the nested types of a class.
9450 * This works only if @klass is non-generic, or a generic type definition.
9452 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9453 * iterate over all of the elements. When no more values are
9454 * available, the return value is NULL.
9456 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9459 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9465 if (!klass->nested_classes_inited)
9466 setup_nested_types (klass);
9469 /* start from the first */
9470 if (klass->ext && klass->ext->nested_classes) {
9471 *iter = klass->ext->nested_classes;
9472 return (MonoClass *)klass->ext->nested_classes->data;
9474 /* no nested types */
9478 item = (GList *)*iter;
9482 return (MonoClass *)item->data;
9489 * mono_class_is_delegate
9490 * @klass: the MonoClass to act on
9492 * Returns: TRUE if the MonoClass represents a System.Delegate.
9495 mono_class_is_delegate (MonoClass *klass)
9497 return klass->delegate;
9501 * mono_class_implements_interface
9502 * @klass: The MonoClass to act on
9503 * @interface: The interface to check if @klass implements.
9505 * Returns: TRUE if @klass implements @interface.
9508 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9510 return mono_class_is_assignable_from (iface, klass);
9514 * mono_field_get_name:
9515 * @field: the MonoClassField to act on
9517 * Returns: The name of the field.
9520 mono_field_get_name (MonoClassField *field)
9526 * mono_field_get_type:
9527 * @field: the MonoClassField to act on
9529 * Returns: MonoType of the field.
9532 mono_field_get_type (MonoClassField *field)
9535 MonoType *type = mono_field_get_type_checked (field, &error);
9536 if (!mono_error_ok (&error)) {
9537 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9538 mono_error_cleanup (&error);
9545 * mono_field_get_type_checked:
9546 * @field: the MonoClassField to act on
9547 * @error: used to return any erro found while retrieving @field type
9549 * Returns: MonoType of the field.
9552 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9554 mono_error_init (error);
9556 mono_field_resolve_type (field, error);
9561 * mono_field_get_parent:
9562 * @field: the MonoClassField to act on
9564 * Returns: MonoClass where the field was defined.
9567 mono_field_get_parent (MonoClassField *field)
9569 return field->parent;
9573 * mono_field_get_flags;
9574 * @field: the MonoClassField to act on
9576 * The metadata flags for a field are encoded using the
9577 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9579 * Returns: The flags for the field.
9582 mono_field_get_flags (MonoClassField *field)
9585 return mono_field_resolve_flags (field);
9586 return field->type->attrs;
9590 * mono_field_get_offset:
9591 * @field: the MonoClassField to act on
9593 * Returns: The field offset.
9596 mono_field_get_offset (MonoClassField *field)
9598 return field->offset;
9602 mono_field_get_rva (MonoClassField *field)
9606 MonoClass *klass = field->parent;
9607 MonoFieldDefaultValue *field_def_values;
9609 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9611 if (!klass->ext || !klass->ext->field_def_values) {
9612 mono_class_alloc_ext (klass);
9614 field_def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9616 mono_image_lock (klass->image);
9617 if (!klass->ext->field_def_values)
9618 klass->ext->field_def_values = field_def_values;
9619 mono_image_unlock (klass->image);
9622 field_index = mono_field_get_index (field);
9624 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9625 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9627 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9628 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9631 return klass->ext->field_def_values [field_index].data;
9635 * mono_field_get_data:
9636 * @field: the MonoClassField to act on
9638 * Returns: A pointer to the metadata constant value or to the field
9639 * data if it has an RVA flag.
9642 mono_field_get_data (MonoClassField *field)
9644 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9645 MonoTypeEnum def_type;
9647 return mono_class_get_field_default_value (field, &def_type);
9648 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9649 return mono_field_get_rva (field);
9656 * mono_property_get_name:
9657 * @prop: the MonoProperty to act on
9659 * Returns: The name of the property
9662 mono_property_get_name (MonoProperty *prop)
9668 * mono_property_get_set_method
9669 * @prop: the MonoProperty to act on.
9671 * Returns: The setter method of the property (A MonoMethod)
9674 mono_property_get_set_method (MonoProperty *prop)
9680 * mono_property_get_get_method
9681 * @prop: the MonoProperty to act on.
9683 * Returns: The setter method of the property (A MonoMethod)
9686 mono_property_get_get_method (MonoProperty *prop)
9692 * mono_property_get_parent:
9693 * @prop: the MonoProperty to act on.
9695 * Returns: The MonoClass where the property was defined.
9698 mono_property_get_parent (MonoProperty *prop)
9700 return prop->parent;
9704 * mono_property_get_flags:
9705 * @prop: the MonoProperty to act on.
9707 * The metadata flags for a property are encoded using the
9708 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9710 * Returns: The flags for the property.
9713 mono_property_get_flags (MonoProperty *prop)
9719 * mono_event_get_name:
9720 * @event: the MonoEvent to act on
9722 * Returns: The name of the event.
9725 mono_event_get_name (MonoEvent *event)
9731 * mono_event_get_add_method:
9732 * @event: The MonoEvent to act on.
9734 * Returns: The @add' method for the event (a MonoMethod).
9737 mono_event_get_add_method (MonoEvent *event)
9743 * mono_event_get_remove_method:
9744 * @event: The MonoEvent to act on.
9746 * Returns: The @remove method for the event (a MonoMethod).
9749 mono_event_get_remove_method (MonoEvent *event)
9751 return event->remove;
9755 * mono_event_get_raise_method:
9756 * @event: The MonoEvent to act on.
9758 * Returns: The @raise method for the event (a MonoMethod).
9761 mono_event_get_raise_method (MonoEvent *event)
9763 return event->raise;
9767 * mono_event_get_parent:
9768 * @event: the MonoEvent to act on.
9770 * Returns: The MonoClass where the event is defined.
9773 mono_event_get_parent (MonoEvent *event)
9775 return event->parent;
9779 * mono_event_get_flags
9780 * @event: the MonoEvent to act on.
9782 * The metadata flags for an event are encoded using the
9783 * EVENT_* constants. See the tabledefs.h file for details.
9785 * Returns: The flags for the event.
9788 mono_event_get_flags (MonoEvent *event)
9790 return event->attrs;
9794 * mono_class_get_method_from_name:
9795 * @klass: where to look for the method
9796 * @name: name of the method
9797 * @param_count: number of parameters. -1 for any number.
9799 * Obtains a MonoMethod with a given name and number of parameters.
9800 * It only works if there are no multiple signatures for any given method name.
9803 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9805 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9809 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9811 MonoMethod *res = NULL;
9814 /* Search directly in the metadata to avoid calling setup_methods () */
9815 for (i = 0; i < klass->method.count; ++i) {
9817 guint32 cols [MONO_METHOD_SIZE];
9819 MonoMethodSignature *sig;
9821 /* klass->method.first points into the methodptr table */
9822 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9824 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9825 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9827 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9830 if (param_count == -1) {
9834 sig = mono_method_signature_checked (method, &error);
9836 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9839 if (sig->param_count == param_count) {
9850 * mono_class_get_method_from_name_flags:
9851 * @klass: where to look for the method
9852 * @name_space: name of the method
9853 * @param_count: number of parameters. -1 for any number.
9854 * @flags: flags which must be set in the method
9856 * Obtains a MonoMethod with a given name and number of parameters.
9857 * It only works if there are no multiple signatures for any given method name.
9860 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9862 MonoMethod *res = NULL;
9865 mono_class_init (klass);
9867 if (klass->generic_class && !klass->methods) {
9868 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9871 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9872 if (!mono_error_ok (&error))
9873 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9878 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9879 mono_class_setup_methods (klass);
9881 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9882 See mono/tests/array_load_exception.il
9883 FIXME we should better report this error to the caller
9885 if (!klass->methods)
9887 for (i = 0; i < klass->method.count; ++i) {
9888 MonoMethod *method = klass->methods [i];
9890 if (method->name[0] == name [0] &&
9891 !strcmp (name, method->name) &&
9892 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9893 ((method->flags & flags) == flags)) {
9900 res = find_method_in_metadata (klass, name, param_count, flags);
9907 * mono_class_set_failure:
9908 * @klass: class in which the failure was detected
9909 * @ex_type: the kind of exception/error to be thrown (later)
9910 * @ex_data: exception data (specific to each type of exception/error)
9912 * Keep a detected failure informations in the class for later processing.
9913 * Note that only the first failure is kept.
9915 * LOCKING: Acquires the loader lock.
9918 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9920 if (mono_class_has_failure (klass))
9923 mono_loader_lock ();
9924 klass->exception_type = ex_type;
9926 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9927 mono_loader_unlock ();
9933 * mono_class_set_type_load_failure:
9934 * @klass: class in which the failure was detected
9935 * @fmt: Printf-style error message string.
9937 * Collect detected failure informaion in the class for later processing.
9938 * The error is stored as a MONO_EXCEPTION_TYPE_LOAD failure.
9939 * Note that only the first failure is kept.
9941 * Returns FALSE if a failure was already set on the class, or TRUE otherwise.
9943 * LOCKING: Acquires the loader lock.
9946 mono_class_set_type_load_failure (MonoClass *klass, const char * fmt, ...)
9948 MonoError prepare_error;
9951 if (mono_class_has_failure (klass))
9954 mono_error_init (&prepare_error);
9956 va_start (args, fmt);
9957 mono_error_vset_type_load_class (&prepare_error, klass, fmt, args);
9960 MonoErrorBoxed *box = mono_error_box (&prepare_error, klass->image);
9961 mono_error_cleanup (&prepare_error);
9962 return mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, box);
9966 * mono_class_get_exception_data:
9968 * Return the exception_data property of KLASS.
9970 * LOCKING: Acquires the loader lock.
9973 mono_class_get_exception_data (MonoClass *klass)
9975 return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9979 * mono_classes_init:
9981 * Initialize the resources used by this module.
9984 mono_classes_init (void)
9986 mono_os_mutex_init (&classes_mutex);
9988 mono_counters_register ("Inflated methods size",
9989 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9990 mono_counters_register ("Inflated classes",
9991 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9992 mono_counters_register ("Inflated classes size",
9993 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9994 mono_counters_register ("MonoClass size",
9995 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9996 mono_counters_register ("MonoClassExt size",
9997 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
10001 * mono_classes_cleanup:
10003 * Free the resources used by this module.
10006 mono_classes_cleanup (void)
10008 if (global_interface_bitset)
10009 mono_bitset_free (global_interface_bitset);
10010 global_interface_bitset = NULL;
10011 mono_os_mutex_destroy (&classes_mutex);
10015 * mono_class_get_exception_for_failure:
10016 * @klass: class in which the failure was detected
10018 * Return a constructed MonoException than the caller can then throw
10019 * using mono_raise_exception - or NULL if no failure is present (or
10020 * doesn't result in an exception).
10023 mono_class_get_exception_for_failure (MonoClass *klass)
10025 gpointer exception_data = mono_class_get_exception_data (klass);
10027 switch (mono_class_get_failure(klass)) {
10028 case MONO_EXCEPTION_MISSING_METHOD:
10029 case MONO_EXCEPTION_MISSING_FIELD:
10030 case MONO_EXCEPTION_FILE_NOT_FOUND:
10031 case MONO_EXCEPTION_BAD_IMAGE:
10032 g_assert_not_reached ();
10033 case MONO_EXCEPTION_TYPE_LOAD:
10034 case MONO_EXCEPTION_INVALID_PROGRAM: {
10035 MonoErrorBoxed *box = (MonoErrorBoxed*)exception_data;
10036 MonoError unboxed_error;
10037 mono_error_init (&unboxed_error);
10038 mono_error_set_from_boxed (&unboxed_error, box);
10039 return mono_error_convert_to_exception (&unboxed_error);
10042 /* TODO - handle other class related failures */
10043 return mono_get_exception_execution_engine ("Unknown class failure");
10049 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
10051 outer_klass = mono_class_get_generic_type_definition (outer_klass);
10052 inner_klass = mono_class_get_generic_type_definition (inner_klass);
10054 if (outer_klass == inner_klass)
10056 inner_klass = inner_klass->nested_in;
10057 } while (inner_klass);
10062 mono_class_get_generic_type_definition (MonoClass *klass)
10064 return klass->generic_class ? klass->generic_class->container_class : klass;
10068 * Check if @klass is a subtype of @parent ignoring generic instantiations.
10070 * Generic instantiations are ignored for all super types of @klass.
10072 * Visibility checks ignoring generic instantiations.
10075 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
10078 klass = mono_class_get_generic_type_definition (klass);
10079 parent = mono_class_get_generic_type_definition (parent);
10080 mono_class_setup_supertypes (klass);
10082 for (i = 0; i < klass->idepth; ++i) {
10083 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
10089 * Subtype can only access parent members with family protection if the site object
10090 * is subclass of Subtype. For example:
10091 * class A { protected int x; }
10093 * void valid_access () {
10097 * void invalid_access () {
10104 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
10106 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
10109 if (context_klass == NULL)
10111 /*if access_klass is not member_klass context_klass must be type compat*/
10112 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10118 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10121 if (accessing == accessed)
10123 if (!accessed || !accessing)
10126 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10127 * anywhere so untrusted friends are not safe to access platform's code internals */
10128 if (mono_security_core_clr_enabled ()) {
10129 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10133 mono_assembly_load_friends (accessed);
10134 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10135 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10136 /* Be conservative with checks */
10137 if (!friend_->name)
10139 if (strcmp (accessing->aname.name, friend_->name))
10141 if (friend_->public_key_token [0]) {
10142 if (!accessing->aname.public_key_token [0])
10144 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10153 * If klass is a generic type or if it is derived from a generic type, return the
10154 * MonoClass of the generic definition
10155 * Returns NULL if not found
10158 get_generic_definition_class (MonoClass *klass)
10161 if (klass->generic_class && klass->generic_class->container_class)
10162 return klass->generic_class->container_class;
10163 klass = klass->parent;
10169 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10172 for (i = 0; i < ginst->type_argc; ++i) {
10173 MonoType *type = ginst->type_argv[i];
10174 switch (type->type) {
10175 case MONO_TYPE_SZARRAY:
10176 if (!can_access_type (access_klass, type->data.klass))
10179 case MONO_TYPE_ARRAY:
10180 if (!can_access_type (access_klass, type->data.array->eklass))
10183 case MONO_TYPE_PTR:
10184 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10187 case MONO_TYPE_CLASS:
10188 case MONO_TYPE_VALUETYPE:
10189 case MONO_TYPE_GENERICINST:
10190 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10200 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10204 if (access_klass == member_klass)
10207 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10210 if (access_klass->element_class && !access_klass->enumtype)
10211 access_klass = access_klass->element_class;
10213 if (member_klass->element_class && !member_klass->enumtype)
10214 member_klass = member_klass->element_class;
10216 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10218 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10221 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
10224 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10227 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10230 /*Non nested type with nested visibility. We just fail it.*/
10231 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10234 switch (access_level) {
10235 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10236 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10238 case TYPE_ATTRIBUTE_PUBLIC:
10241 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10244 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10245 return is_nesting_type (member_klass, access_klass);
10247 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10248 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10250 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10251 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10253 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10254 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10255 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10257 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10258 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10259 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10264 /* FIXME: check visibility of type, too */
10266 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10268 MonoClass *member_generic_def;
10269 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10272 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
10273 access_klass->generic_container) &&
10274 (member_generic_def = get_generic_definition_class (member_klass))) {
10275 MonoClass *access_container;
10277 if (access_klass->generic_container)
10278 access_container = access_klass;
10280 access_container = access_klass->generic_class->container_class;
10282 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10286 /* Partition I 8.5.3.2 */
10287 /* the access level values are the same for fields and methods */
10288 switch (access_level) {
10289 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10290 /* same compilation unit */
10291 return access_klass->image == member_klass->image;
10292 case FIELD_ATTRIBUTE_PRIVATE:
10293 return access_klass == member_klass;
10294 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10295 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10296 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10299 case FIELD_ATTRIBUTE_ASSEMBLY:
10300 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10301 case FIELD_ATTRIBUTE_FAMILY:
10302 if (is_valid_family_access (access_klass, member_klass, context_klass))
10305 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10306 if (is_valid_family_access (access_klass, member_klass, context_klass))
10308 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10309 case FIELD_ATTRIBUTE_PUBLIC:
10316 * mono_method_can_access_field:
10317 * @method: Method that will attempt to access the field
10318 * @field: the field to access
10320 * Used to determine if a method is allowed to access the specified field.
10322 * Returns: TRUE if the given @method is allowed to access the @field while following
10323 * the accessibility rules of the CLI.
10326 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10328 /* FIXME: check all overlapping fields */
10329 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10331 MonoClass *nested = method->klass->nested_in;
10333 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10336 nested = nested->nested_in;
10343 * mono_method_can_access_method:
10344 * @method: Method that will attempt to access the other method
10345 * @called: the method that we want to probe for accessibility.
10347 * Used to determine if the @method is allowed to access the specified @called method.
10349 * Returns: TRUE if the given @method is allowed to invoke the @called while following
10350 * the accessibility rules of the CLI.
10353 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10355 method = mono_method_get_method_definition (method);
10356 called = mono_method_get_method_definition (called);
10357 return mono_method_can_access_method_full (method, called, NULL);
10361 * mono_method_can_access_method_full:
10362 * @method: The caller method
10363 * @called: The called method
10364 * @context_klass: The static type on stack of the owner @called object used
10366 * This function must be used with instance calls, as they have more strict family accessibility.
10367 * It can be used with static methods, but context_klass should be NULL.
10369 * Returns: TRUE if caller have proper visibility and acessibility to @called
10372 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10374 /* Wrappers are except from access checks */
10375 if (method->wrapper_type != MONO_WRAPPER_NONE || called->wrapper_type != MONO_WRAPPER_NONE)
10378 MonoClass *access_class = method->klass;
10379 MonoClass *member_class = called->klass;
10380 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10382 MonoClass *nested = access_class->nested_in;
10384 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10387 nested = nested->nested_in;
10394 can = can_access_type (access_class, member_class);
10396 MonoClass *nested = access_class->nested_in;
10398 can = can_access_type (nested, member_class);
10401 nested = nested->nested_in;
10408 if (called->is_inflated) {
10409 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10410 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10419 * mono_method_can_access_field_full:
10420 * @method: The caller method
10421 * @field: The accessed field
10422 * @context_klass: The static type on stack of the owner @field object used
10424 * This function must be used with instance fields, as they have more strict family accessibility.
10425 * It can be used with static fields, but context_klass should be NULL.
10427 * Returns: TRUE if caller have proper visibility and acessibility to @field
10430 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10432 MonoClass *access_class = method->klass;
10433 MonoClass *member_class = field->parent;
10434 /* FIXME: check all overlapping fields */
10435 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10437 MonoClass *nested = access_class->nested_in;
10439 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10442 nested = nested->nested_in;
10449 can = can_access_type (access_class, member_class);
10451 MonoClass *nested = access_class->nested_in;
10453 can = can_access_type (nested, member_class);
10456 nested = nested->nested_in;
10466 * mono_class_can_access_class:
10467 * @source_class: The source class
10468 * @target_class: The accessed class
10470 * This function returns is @target_class is visible to @source_class
10472 * Returns: TRUE if source have proper visibility and acessibility to target
10475 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10477 return can_access_type (source_class, target_class);
10481 * mono_type_is_valid_enum_basetype:
10482 * @type: The MonoType to check
10484 * Returns: TRUE if the type can be used as the basetype of an enum
10486 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10487 switch (type->type) {
10490 case MONO_TYPE_BOOLEAN:
10493 case MONO_TYPE_CHAR:
10507 * mono_class_is_valid_enum:
10508 * @klass: An enum class to be validated
10510 * This method verify the required properties an enum should have.
10512 * Returns: TRUE if the informed enum class is valid
10514 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10515 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10516 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10518 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10519 MonoClassField * field;
10520 gpointer iter = NULL;
10521 gboolean found_base_field = FALSE;
10523 g_assert (klass->enumtype);
10524 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10525 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10529 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10532 while ((field = mono_class_get_fields (klass, &iter))) {
10533 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10534 if (found_base_field)
10536 found_base_field = TRUE;
10537 if (!mono_type_is_valid_enum_basetype (field->type))
10542 if (!found_base_field)
10545 if (klass->method.count > 0)
10552 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10554 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10558 * mono_class_setup_interface_id:
10560 * Initializes MonoClass::interface_id if required.
10562 * LOCKING: Acquires the loader lock.
10565 mono_class_setup_interface_id (MonoClass *klass)
10567 mono_loader_lock ();
10568 if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10569 klass->interface_id = mono_get_unique_iid (klass);
10570 mono_loader_unlock ();
10574 * mono_class_alloc_ext:
10576 * Allocate klass->ext if not already done.
10579 mono_class_alloc_ext (MonoClass *klass)
10586 ext = (MonoClassExt *)mono_class_alloc0 (klass, sizeof (MonoClassExt));
10587 mono_image_lock (klass->image);
10588 mono_memory_barrier ();
10591 class_ext_size += sizeof (MonoClassExt);
10592 mono_image_unlock (klass->image);
10596 * mono_class_setup_interfaces:
10598 * Initialize klass->interfaces/interfaces_count.
10599 * LOCKING: Acquires the loader lock.
10600 * This function can fail the type.
10603 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10605 int i, interface_count;
10606 MonoClass **interfaces;
10608 mono_error_init (error);
10610 if (klass->interfaces_inited)
10613 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10614 MonoType *args [1];
10616 /* generic IList, ICollection, IEnumerable */
10617 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10618 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10620 args [0] = &klass->element_class->byval_arg;
10621 interfaces [0] = mono_class_bind_generic_parameters (
10622 mono_defaults.generic_ilist_class, 1, args, FALSE);
10623 if (interface_count > 1)
10624 interfaces [1] = mono_class_bind_generic_parameters (
10625 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10626 } else if (klass->generic_class) {
10627 MonoClass *gklass = klass->generic_class->container_class;
10629 mono_class_setup_interfaces (gklass, error);
10630 if (!mono_error_ok (error)) {
10631 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10635 interface_count = gklass->interface_count;
10636 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10637 for (i = 0; i < interface_count; i++) {
10638 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10639 if (!mono_error_ok (error)) {
10640 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10645 interface_count = 0;
10649 mono_image_lock (klass->image);
10651 if (!klass->interfaces_inited) {
10652 klass->interface_count = interface_count;
10653 klass->interfaces = interfaces;
10655 mono_memory_barrier ();
10657 klass->interfaces_inited = TRUE;
10660 mono_image_unlock (klass->image);
10664 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10666 MonoClass *klass = field->parent;
10667 MonoImage *image = klass->image;
10668 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10669 int field_idx = field - klass->fields;
10671 mono_error_init (error);
10674 MonoClassField *gfield = >d->fields [field_idx];
10675 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10676 if (!mono_error_ok (error)) {
10677 mono_class_set_type_load_failure (klass, "Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10680 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10681 if (!mono_error_ok (error)) {
10682 mono_class_set_type_load_failure (klass, "Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10686 guint32 cols [MONO_FIELD_SIZE];
10687 MonoGenericContainer *container = NULL;
10688 int idx = klass->field.first + field_idx;
10690 /*FIXME, in theory we do not lazy load SRE fields*/
10691 g_assert (!image_is_dynamic (image));
10693 if (klass->generic_container) {
10694 container = klass->generic_container;
10696 container = gtd->generic_container;
10697 g_assert (container);
10700 /* klass->field.first and idx points into the fieldptr table */
10701 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10703 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10704 mono_error_set_type_load_class (error, klass, "Could not verify field %s signature", field->name);;
10705 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
10709 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10711 mono_metadata_decode_value (sig, &sig);
10712 /* FIELD signature == 0x06 */
10713 g_assert (*sig == 0x06);
10715 field->type = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10716 if (!field->type) {
10717 mono_class_set_type_load_failure (klass, "Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10723 mono_field_resolve_flags (MonoClassField *field)
10725 MonoClass *klass = field->parent;
10726 MonoImage *image = klass->image;
10727 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10728 int field_idx = field - klass->fields;
10732 MonoClassField *gfield = >d->fields [field_idx];
10733 return mono_field_get_flags (gfield);
10735 int idx = klass->field.first + field_idx;
10737 /*FIXME, in theory we do not lazy load SRE fields*/
10738 g_assert (!image_is_dynamic (image));
10740 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10745 * mono_class_setup_basic_field_info:
10746 * @class: The class to initialize
10748 * Initializes the klass->fields array of fields.
10749 * Aquires the loader lock.
10752 mono_class_setup_basic_field_info_locking (MonoClass *klass)
10754 mono_loader_lock ();
10755 mono_class_setup_basic_field_info (klass);
10756 mono_loader_unlock ();
10760 * mono_class_get_fields_lazy:
10761 * @klass: the MonoClass to act on
10763 * This routine is an iterator routine for retrieving the fields in a class.
10764 * Only minimal information about fields are loaded. Accessors must be used
10765 * for all MonoClassField returned.
10767 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10768 * iterate over all of the elements. When no more values are
10769 * available, the return value is NULL.
10771 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10774 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10776 MonoClassField* field;
10780 mono_class_setup_basic_field_info_locking (klass);
10781 if (!klass->fields)
10783 /* start from the first */
10784 if (klass->field.count) {
10785 *iter = &klass->fields [0];
10786 return (MonoClassField *)*iter;
10792 field = (MonoClassField *)*iter;
10794 if (field < &klass->fields [klass->field.count]) {
10796 return (MonoClassField *)*iter;
10802 mono_class_full_name (MonoClass *klass)
10804 return mono_type_full_name (&klass->byval_arg);
10807 /* Declare all shared lazy type lookup functions */
10808 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, System.Runtime.InteropServices, SafeHandle)