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, MonoErrorBoxed *boxed_error);
81 static gpointer mono_class_get_exception_data (const MonoClass *klass);
85 We use gclass recording to allow recursive system f types to be referenced by a parent.
87 Given the following type hierarchy:
89 class TextBox : TextBoxBase<TextBox> {}
90 class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
91 class TextInput<T> : Input<T> where T: TextInput<T> {}
94 The runtime tries to load TextBoxBase<>.
95 To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
96 To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
97 To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
99 At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded
100 at this point, iow, both are registered in the type map and both and a NULL parent. This means
101 that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
103 To fix that what we do is to record all generic instantes created while resolving the parent of
104 any generic type definition and, after resolved, correct the parent field if needed.
107 static int record_gclass_instantiation;
108 static GSList *gclass_recorded_list;
109 typedef gboolean (*gclass_record_func) (MonoClass*, void*);
114 mono_locks_os_acquire (&classes_mutex, ClassesLock);
118 classes_unlock (void)
120 mono_locks_os_release (&classes_mutex, ClassesLock);
124 * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
127 enable_gclass_recording (void)
129 ++record_gclass_instantiation;
133 * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
136 disable_gclass_recording (gclass_record_func func, void *user_data)
138 GSList **head = &gclass_recorded_list;
140 g_assert (record_gclass_instantiation > 0);
141 --record_gclass_instantiation;
144 GSList *node = *head;
145 if (func ((MonoClass*)node->data, user_data)) {
147 g_slist_free_1 (node);
153 /* We automatically discard all recorded gclasses when disabled. */
154 if (!record_gclass_instantiation && gclass_recorded_list) {
155 g_slist_free (gclass_recorded_list);
156 gclass_recorded_list = NULL;
161 * mono_class_from_typeref:
162 * @image: a MonoImage
163 * @type_token: a TypeRef token
165 * Creates the MonoClass* structure representing the type defined by
166 * the typeref token valid inside @image.
167 * Returns: The MonoClass* representing the typeref token, NULL ifcould
171 mono_class_from_typeref (MonoImage *image, guint32 type_token)
174 MonoClass *klass = mono_class_from_typeref_checked (image, type_token, &error);
175 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
180 * mono_class_from_typeref_checked:
181 * @image: a MonoImage
182 * @type_token: a TypeRef token
183 * @error: error return code, if any.
185 * Creates the MonoClass* structure representing the type defined by
186 * the typeref token valid inside @image.
188 * Returns: The MonoClass* representing the typeref token, NULL if it could
189 * not be loaded with the @error value filled with the information about the
193 mono_class_from_typeref_checked (MonoImage *image, guint32 type_token, MonoError *error)
195 guint32 cols [MONO_TYPEREF_SIZE];
196 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
198 const char *name, *nspace;
199 MonoClass *res = NULL;
202 mono_error_init (error);
204 if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, error))
207 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
209 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
210 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
212 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
213 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
214 case MONO_RESOLUTION_SCOPE_MODULE:
216 LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
217 This is not the observed behavior of existing implementations.
218 The defacto behavior is that it's just a typedef in disguise.
220 /* a typedef in disguise */
221 res = mono_class_from_name_checked (image, nspace, name, error);
224 case MONO_RESOLUTION_SCOPE_MODULEREF:
225 module = mono_image_load_module_checked (image, idx, error);
227 res = mono_class_from_name_checked (module, nspace, name, error);
230 case MONO_RESOLUTION_SCOPE_TYPEREF: {
231 MonoClass *enclosing;
234 if (idx == mono_metadata_token_index (type_token)) {
235 mono_error_set_bad_image (error, image, "Image with self-referencing typeref token %08x.", type_token);
239 enclosing = mono_class_from_typeref_checked (image, MONO_TOKEN_TYPE_REF | idx, error);
240 return_val_if_nok (error, NULL);
242 if (enclosing->nested_classes_inited && enclosing->ext) {
243 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
244 for (tmp = enclosing->ext->nested_classes; tmp; tmp = tmp->next) {
245 res = (MonoClass *)tmp->data;
246 if (strcmp (res->name, name) == 0)
250 /* Don't call mono_class_init as we might've been called by it recursively */
251 int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
253 guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
254 guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
255 const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
257 if (strcmp (nname, name) == 0)
258 return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, error);
260 i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
263 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name);
266 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
270 if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) {
271 mono_error_set_bad_image (error, image, "Image with invalid assemblyref token %08x.", idx);
275 if (!image->references || !image->references [idx - 1])
276 mono_assembly_load_reference (image, idx - 1);
277 g_assert (image->references [idx - 1]);
279 /* If the assembly did not load, register this as a type load exception */
280 if (image->references [idx - 1] == REFERENCE_MISSING){
281 MonoAssemblyName aname;
284 mono_assembly_get_assemblyref (image, idx - 1, &aname);
285 human_name = mono_stringify_assembly_name (&aname);
286 mono_error_set_assembly_load_simple (error, human_name, image->assembly ? image->assembly->ref_only : FALSE);
290 res = mono_class_from_name_checked (image->references [idx - 1]->image, nspace, name, error);
293 /* Generic case, should be avoided for when a better error is possible. */
294 if (!res && mono_error_ok (error)) {
295 char *name = mono_class_name_from_token (image, type_token);
296 char *assembly = mono_assembly_name_from_token (image, type_token);
297 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
304 mono_image_memdup (MonoImage *image, void *data, guint size)
306 void *res = mono_image_alloc (image, size);
307 memcpy (res, data, size);
311 /* Copy everything mono_metadata_free_array free. */
313 mono_dup_array_type (MonoImage *image, MonoArrayType *a)
316 a = (MonoArrayType *)mono_image_memdup (image, a, sizeof (MonoArrayType));
318 a->sizes = (int *)mono_image_memdup (image, a->sizes, a->numsizes * sizeof (int));
320 a->lobounds = (int *)mono_image_memdup (image, a->lobounds, a->numlobounds * sizeof (int));
322 a = (MonoArrayType *)g_memdup (a, sizeof (MonoArrayType));
324 a->sizes = (int *)g_memdup (a->sizes, a->numsizes * sizeof (int));
326 a->lobounds = (int *)g_memdup (a->lobounds, a->numlobounds * sizeof (int));
331 /* Copy everything mono_metadata_free_method_signature free. */
333 mono_metadata_signature_deep_dup (MonoImage *image, MonoMethodSignature *sig)
337 sig = mono_metadata_signature_dup_full (image, sig);
339 sig->ret = mono_metadata_type_dup (image, sig->ret);
340 for (i = 0; i < sig->param_count; ++i)
341 sig->params [i] = mono_metadata_type_dup (image, sig->params [i]);
347 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
349 MonoAssembly *ta = klass->image->assembly;
352 name = mono_stringify_assembly_name (&ta->aname);
353 g_string_append_printf (str, ", %s", name);
358 mono_type_name_check_byref (MonoType *type, GString *str)
361 g_string_append_c (str, '&');
365 * mono_identifier_escape_type_name_chars:
366 * @str: a destination string
367 * @identifier: an IDENTIFIER in internal form
371 * The displayed form of the identifier is appended to str.
373 * The displayed form of an identifier has the characters ,+&*[]\
374 * that have special meaning in type names escaped with a preceeding
375 * backslash (\) character.
378 mono_identifier_escape_type_name_chars (GString* str, const char* identifier)
384 // reserve space for common case: there will be no escaped characters.
385 g_string_set_size(str, n + strlen(identifier));
386 g_string_set_size(str, n);
388 for (const char* s = identifier; *s != 0 ; s++) {
397 g_string_append_c (str, '\\');
398 g_string_append_c (str, *s);
401 g_string_append_c (str, *s);
409 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
410 MonoTypeNameFormat format)
414 switch (type->type) {
415 case MONO_TYPE_ARRAY: {
416 int i, rank = type->data.array->rank;
417 MonoTypeNameFormat nested_format;
419 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
420 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
422 mono_type_get_name_recurse (
423 &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
424 g_string_append_c (str, '[');
426 g_string_append_c (str, '*');
427 for (i = 1; i < rank; i++)
428 g_string_append_c (str, ',');
429 g_string_append_c (str, ']');
431 mono_type_name_check_byref (type, str);
433 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
434 _mono_type_get_assembly_name (type->data.array->eklass, str);
437 case MONO_TYPE_SZARRAY: {
438 MonoTypeNameFormat nested_format;
440 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
441 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
443 mono_type_get_name_recurse (
444 &type->data.klass->byval_arg, str, FALSE, nested_format);
445 g_string_append (str, "[]");
447 mono_type_name_check_byref (type, str);
449 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
450 _mono_type_get_assembly_name (type->data.klass, str);
453 case MONO_TYPE_PTR: {
454 MonoTypeNameFormat nested_format;
456 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
457 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
459 mono_type_get_name_recurse (
460 type->data.type, str, FALSE, nested_format);
461 g_string_append_c (str, '*');
463 mono_type_name_check_byref (type, str);
465 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
466 _mono_type_get_assembly_name (mono_class_from_mono_type (type->data.type), str);
471 if (!mono_generic_param_info (type->data.generic_param))
472 g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num);
474 g_string_append (str, mono_generic_param_info (type->data.generic_param)->name);
476 mono_type_name_check_byref (type, str);
480 klass = mono_class_from_mono_type (type);
481 if (klass->nested_in) {
482 mono_type_get_name_recurse (
483 &klass->nested_in->byval_arg, str, TRUE, format);
484 if (format == MONO_TYPE_NAME_FORMAT_IL)
485 g_string_append_c (str, '.');
487 g_string_append_c (str, '+');
488 } else if (*klass->name_space) {
489 if (format == MONO_TYPE_NAME_FORMAT_IL)
490 g_string_append (str, klass->name_space);
492 mono_identifier_escape_type_name_chars (str, klass->name_space);
493 g_string_append_c (str, '.');
495 if (format == MONO_TYPE_NAME_FORMAT_IL) {
496 char *s = strchr (klass->name, '`');
497 int len = s ? s - klass->name : strlen (klass->name);
498 g_string_append_len (str, klass->name, len);
500 mono_identifier_escape_type_name_chars (str, klass->name);
504 if (klass->generic_class) {
505 MonoGenericClass *gclass = klass->generic_class;
506 MonoGenericInst *inst = gclass->context.class_inst;
507 MonoTypeNameFormat nested_format;
510 nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
511 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
513 if (format == MONO_TYPE_NAME_FORMAT_IL)
514 g_string_append_c (str, '<');
516 g_string_append_c (str, '[');
517 for (i = 0; i < inst->type_argc; i++) {
518 MonoType *t = inst->type_argv [i];
521 g_string_append_c (str, ',');
522 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
523 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
524 g_string_append_c (str, '[');
525 mono_type_get_name_recurse (inst->type_argv [i], str, FALSE, nested_format);
526 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
527 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
528 g_string_append_c (str, ']');
530 if (format == MONO_TYPE_NAME_FORMAT_IL)
531 g_string_append_c (str, '>');
533 g_string_append_c (str, ']');
534 } else if (klass->generic_container &&
535 (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
536 (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
539 if (format == MONO_TYPE_NAME_FORMAT_IL)
540 g_string_append_c (str, '<');
542 g_string_append_c (str, '[');
543 for (i = 0; i < klass->generic_container->type_argc; i++) {
545 g_string_append_c (str, ',');
546 g_string_append (str, mono_generic_container_get_param_info (klass->generic_container, i)->name);
548 if (format == MONO_TYPE_NAME_FORMAT_IL)
549 g_string_append_c (str, '>');
551 g_string_append_c (str, ']');
554 mono_type_name_check_byref (type, str);
556 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
557 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
558 _mono_type_get_assembly_name (klass, str);
564 * mono_type_get_name_full:
566 * @format: the format for the return string.
569 * Returns: The string representation in a number of formats:
571 * if format is MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
572 * returned in the formatrequired by System.Reflection, this is the
573 * inverse of mono_reflection_parse_type ().
575 * if format is MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
576 * be used by the IL assembler.
578 * if format is MONO_TYPE_NAME_FORMAT_FULL_NAME
580 * if format is MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
583 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
587 result = g_string_new ("");
589 mono_type_get_name_recurse (type, result, FALSE, format);
591 return g_string_free (result, FALSE);
595 * mono_type_get_full_name:
598 * Returns: The string representation for type as required by System.Reflection.
599 * The inverse of mono_reflection_parse_type ().
602 mono_type_get_full_name (MonoClass *klass)
604 return mono_type_get_name_full (mono_class_get_type (klass), MONO_TYPE_NAME_FORMAT_REFLECTION);
608 * mono_type_get_name:
611 * Returns: The string representation for type as it would be represented in IL code.
614 mono_type_get_name (MonoType *type)
616 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
620 * mono_type_get_underlying_type:
623 * Returns: The MonoType for the underlying integer type if @type
624 * is an enum and byref is false, otherwise the type itself.
627 mono_type_get_underlying_type (MonoType *type)
629 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype && !type->byref)
630 return mono_class_enum_basetype (type->data.klass);
631 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype && !type->byref)
632 return mono_class_enum_basetype (type->data.generic_class->container_class);
637 * mono_class_is_open_constructed_type:
640 * Returns: TRUE if type represents a generics open constructed type.
641 * IOW, not all type parameters required for the instantiation have
642 * been provided or it's a generic type definition.
644 * An open constructed type means it's a non realizable type. Not to
645 * be mixed up with an abstract type - we can't cast or dispatch to
646 * an open type, for example.
649 mono_class_is_open_constructed_type (MonoType *t)
655 case MONO_TYPE_SZARRAY:
656 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
657 case MONO_TYPE_ARRAY:
658 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
660 return mono_class_is_open_constructed_type (t->data.type);
661 case MONO_TYPE_GENERICINST:
662 return t->data.generic_class->context.class_inst->is_open;
663 case MONO_TYPE_CLASS:
664 case MONO_TYPE_VALUETYPE:
665 return t->data.klass->generic_container != NULL;
672 This is a simple function to catch the most common bad instances of generic types.
673 Specially those that might lead to further failures in the runtime.
676 is_valid_generic_argument (MonoType *type)
678 switch (type->type) {
680 //case MONO_TYPE_TYPEDBYREF:
688 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
690 mono_error_init (error);
692 switch (type->type) {
693 case MONO_TYPE_MVAR: {
695 int num = mono_type_get_generic_param_num (type);
696 MonoGenericInst *inst = context->method_inst;
699 if (num >= inst->type_argc) {
700 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
701 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
702 num, info ? info->name : "", inst->type_argc);
706 if (!is_valid_generic_argument (inst->type_argv [num])) {
707 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
708 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
709 num, info ? info->name : "", inst->type_argv [num]->type);
713 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
714 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
715 * ->byref and ->attrs from @type are propagated to the returned type.
717 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
718 nt->byref = type->byref;
719 nt->attrs = type->attrs;
722 case MONO_TYPE_VAR: {
724 int num = mono_type_get_generic_param_num (type);
725 MonoGenericInst *inst = context->class_inst;
728 if (num >= inst->type_argc) {
729 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
730 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
731 num, info ? info->name : "", inst->type_argc);
734 if (!is_valid_generic_argument (inst->type_argv [num])) {
735 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
736 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
737 num, info ? info->name : "", inst->type_argv [num]->type);
740 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
741 nt->byref = type->byref;
742 nt->attrs = type->attrs;
745 case MONO_TYPE_SZARRAY: {
746 MonoClass *eclass = type->data.klass;
747 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
748 if (!inflated || !mono_error_ok (error))
750 nt = mono_metadata_type_dup (image, type);
751 nt->data.klass = mono_class_from_mono_type (inflated);
752 mono_metadata_free_type (inflated);
755 case MONO_TYPE_ARRAY: {
756 MonoClass *eclass = type->data.array->eklass;
757 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
758 if (!inflated || !mono_error_ok (error))
760 nt = mono_metadata_type_dup (image, type);
761 nt->data.array->eklass = mono_class_from_mono_type (inflated);
762 mono_metadata_free_type (inflated);
765 case MONO_TYPE_GENERICINST: {
766 MonoGenericClass *gclass = type->data.generic_class;
767 MonoGenericInst *inst;
769 if (!gclass->context.class_inst->is_open)
772 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
773 return_val_if_nok (error, NULL);
775 if (inst != gclass->context.class_inst)
776 gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
778 if (gclass == type->data.generic_class)
781 nt = mono_metadata_type_dup (image, type);
782 nt->data.generic_class = gclass;
785 case MONO_TYPE_CLASS:
786 case MONO_TYPE_VALUETYPE: {
787 MonoClass *klass = type->data.klass;
788 MonoGenericContainer *container = klass->generic_container;
789 MonoGenericInst *inst;
790 MonoGenericClass *gclass = NULL;
796 /* We can't use context->class_inst directly, since it can have more elements */
797 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
798 return_val_if_nok (error, NULL);
800 if (inst == container->context.class_inst)
803 gclass = mono_metadata_lookup_generic_class (klass, inst, image_is_dynamic (klass->image));
805 nt = mono_metadata_type_dup (image, type);
806 nt->type = MONO_TYPE_GENERICINST;
807 nt->data.generic_class = gclass;
817 mono_generic_class_get_context (MonoGenericClass *gclass)
819 return &gclass->context;
823 mono_class_get_context (MonoClass *klass)
825 return klass->generic_class ? mono_generic_class_get_context (klass->generic_class) : NULL;
829 * mono_class_get_generic_container:
831 * Return the generic container of KLASS which should be a generic type definition.
833 MonoGenericContainer*
834 mono_class_get_generic_container (MonoClass *klass)
836 g_assert (klass->is_generic);
838 return klass->generic_container;
842 * mono_class_get_generic_class:
844 * Return the MonoGenericClass of KLASS, which should be a generic instance.
847 mono_class_get_generic_class (MonoClass *klass)
849 g_assert (klass->is_inflated);
851 return klass->generic_class;
855 * mono_class_inflate_generic_type_with_mempool:
856 * @mempool: a mempool
858 * @context: a generics context
859 * @error: error context
861 * The same as mono_class_inflate_generic_type, but allocates the MonoType
862 * from mempool if it is non-NULL. If it is NULL, the MonoType is
863 * allocated on the heap and is owned by the caller.
864 * The returned type can potentially be the same as TYPE, so it should not be
865 * modified by the caller, and it should be freed using mono_metadata_free_type ().
868 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
870 MonoType *inflated = NULL;
871 mono_error_init (error);
874 inflated = inflate_generic_type (image, type, context, error);
875 return_val_if_nok (error, NULL);
878 MonoType *shared = mono_metadata_get_shared_type (type);
883 return mono_metadata_type_dup (image, type);
887 mono_stats.inflated_type_count++;
892 * mono_class_inflate_generic_type:
894 * @context: a generics context
896 * If @type is a generic type and @context is not NULL, instantiate it using the
897 * generics context @context.
899 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
900 * on the heap and is owned by the caller. Returns NULL on error.
902 * @deprecated Please use mono_class_inflate_generic_type_checked instead
905 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
909 result = mono_class_inflate_generic_type_checked (type, context, &error);
910 mono_error_cleanup (&error);
915 * mono_class_inflate_generic_type:
917 * @context: a generics context
918 * @error: error context to use
920 * If @type is a generic type and @context is not NULL, instantiate it using the
921 * generics context @context.
923 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
924 * on the heap and is owned by the caller.
927 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
929 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
933 * mono_class_inflate_generic_type_no_copy:
935 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
939 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
941 MonoType *inflated = NULL;
943 mono_error_init (error);
945 inflated = inflate_generic_type (image, type, context, error);
946 return_val_if_nok (error, NULL);
952 mono_stats.inflated_type_count++;
957 * mono_class_inflate_generic_class:
959 * Inflate the class @gklass with @context. Set @error on failure.
962 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
967 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
968 return_val_if_nok (error, NULL);
970 res = mono_class_from_mono_type (inflated);
971 mono_metadata_free_type (inflated);
976 static MonoGenericContext
977 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
979 MonoGenericInst *class_inst = NULL;
980 MonoGenericInst *method_inst = NULL;
981 MonoGenericContext res = { NULL, NULL };
983 mono_error_init (error);
985 if (context->class_inst) {
986 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
987 if (!mono_error_ok (error))
991 if (context->method_inst) {
992 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
993 if (!mono_error_ok (error))
997 res.class_inst = class_inst;
998 res.method_inst = method_inst;
1004 * mono_class_inflate_generic_method:
1005 * @method: a generic method
1006 * @context: a generics context
1008 * Instantiate the generic method @method using the generics context @context.
1010 * Returns: The new instantiated method
1013 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
1015 return mono_class_inflate_generic_method_full (method, NULL, context);
1019 mono_class_inflate_generic_method_checked (MonoMethod *method, MonoGenericContext *context, MonoError *error)
1021 return mono_class_inflate_generic_method_full_checked (method, NULL, context, error);
1025 * mono_class_inflate_generic_method_full:
1027 * Instantiate method @method with the generic context @context.
1028 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
1029 * Use mono_method_signature () and mono_method_get_header () to get the correct values.
1032 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
1035 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
1036 if (!mono_error_ok (&error))
1037 /*FIXME do proper error handling - on this case, kill this function. */
1038 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
1044 * mono_class_inflate_generic_method_full_checked:
1045 * Same as mono_class_inflate_generic_method_full but return failure using @error.
1048 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
1051 MonoMethodInflated *iresult, *cached;
1052 MonoMethodSignature *sig;
1053 MonoGenericContext tmp_context;
1055 mono_error_init (error);
1057 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1058 while (method->is_inflated) {
1059 MonoGenericContext *method_context = mono_method_get_context (method);
1060 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1062 tmp_context = inflate_generic_context (method_context, context, error);
1063 return_val_if_nok (error, NULL);
1065 context = &tmp_context;
1067 if (mono_metadata_generic_context_equal (method_context, context))
1070 method = imethod->declaring;
1074 * A method only needs to be inflated if the context has argument for which it is
1077 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1078 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1081 if (!((method->is_generic && context->method_inst) ||
1082 (method->klass->generic_container && context->class_inst)))
1085 iresult = g_new0 (MonoMethodInflated, 1);
1086 iresult->context = *context;
1087 iresult->declaring = method;
1089 if (!context->method_inst && method->is_generic)
1090 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1092 if (!context->class_inst) {
1093 g_assert (!iresult->declaring->klass->generic_class);
1094 if (iresult->declaring->klass->generic_container)
1095 iresult->context.class_inst = iresult->declaring->klass->generic_container->context.class_inst;
1096 else if (iresult->declaring->klass->generic_class)
1097 iresult->context.class_inst = iresult->declaring->klass->generic_class->context.class_inst;
1099 /* This can happen with some callers like mono_object_get_virtual_method () */
1100 if (!iresult->declaring->klass->generic_container && !iresult->declaring->klass->generic_class)
1101 iresult->context.class_inst = NULL;
1103 MonoImageSet *set = mono_metadata_get_image_set_for_method (iresult);
1106 mono_image_set_lock (set);
1107 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1108 mono_image_set_unlock (set);
1112 return (MonoMethod*)cached;
1115 mono_stats.inflated_method_count++;
1117 inflated_methods_size += sizeof (MonoMethodInflated);
1119 sig = mono_method_signature (method);
1121 char *name = mono_type_get_full_name (method->klass);
1122 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1128 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1130 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1133 result = (MonoMethod *) iresult;
1134 result->is_inflated = TRUE;
1135 result->is_generic = FALSE;
1136 result->sre_method = FALSE;
1137 result->signature = NULL;
1139 if (method->wrapper_type) {
1140 MonoMethodWrapper *mw = (MonoMethodWrapper*)method;
1141 MonoMethodWrapper *resw = (MonoMethodWrapper*)result;
1142 int len = GPOINTER_TO_INT (((void**)mw->method_data) [0]);
1144 resw->method_data = (void **)g_malloc (sizeof (gpointer) * (len + 1));
1145 memcpy (resw->method_data, mw->method_data, sizeof (gpointer) * (len + 1));
1148 if (iresult->context.method_inst) {
1149 /* Set the generic_container of the result to the generic_container of method */
1150 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1152 if (generic_container && iresult->context.method_inst == generic_container->context.method_inst) {
1153 result->is_generic = 1;
1154 mono_method_set_generic_container (result, generic_container);
1158 if (!klass_hint || !klass_hint->generic_class ||
1159 klass_hint->generic_class->container_class != method->klass ||
1160 klass_hint->generic_class->context.class_inst != context->class_inst)
1163 if (method->klass->generic_container)
1164 result->klass = klass_hint;
1166 if (!result->klass) {
1167 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1168 if (!mono_error_ok (error))
1171 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1173 mono_metadata_free_type (inflated);
1177 * FIXME: This should hold, but it doesn't:
1179 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1180 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1181 * g_assert (result->is_generic);
1184 * Fixing this here causes other things to break, hence a very
1185 * ugly hack in mini-trampolines.c - see
1186 * is_generic_method_definition().
1190 mono_image_set_lock (set);
1191 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1193 g_hash_table_insert (set->gmethod_cache, iresult, iresult);
1194 iresult->owner = set;
1197 mono_image_set_unlock (set);
1199 return (MonoMethod*)cached;
1207 * mono_get_inflated_method:
1209 * Obsolete. We keep it around since it's mentioned in the public API.
1212 mono_get_inflated_method (MonoMethod *method)
1218 * mono_method_get_context_general:
1220 * @uninflated: handle uninflated methods?
1222 * Returns the generic context of a method or NULL if it doesn't have
1223 * one. For an inflated method that's the context stored in the
1224 * method. Otherwise it's in the method's generic container or in the
1225 * generic container of the method's class.
1228 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1230 if (method->is_inflated) {
1231 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1232 return &imethod->context;
1236 if (method->is_generic)
1237 return &(mono_method_get_generic_container (method)->context);
1238 if (method->klass->generic_container)
1239 return &method->klass->generic_container->context;
1244 * mono_method_get_context:
1247 * Returns the generic context for method if it's inflated, otherwise
1251 mono_method_get_context (MonoMethod *method)
1253 return mono_method_get_context_general (method, FALSE);
1257 * mono_method_get_generic_container:
1259 * Returns the generic container of METHOD, which should be a generic method definition.
1260 * Returns NULL if METHOD is not a generic method definition.
1261 * LOCKING: Acquires the loader lock.
1263 MonoGenericContainer*
1264 mono_method_get_generic_container (MonoMethod *method)
1266 MonoGenericContainer *container;
1268 if (!method->is_generic)
1271 container = (MonoGenericContainer *)mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1272 g_assert (container);
1278 * mono_method_set_generic_container:
1280 * Sets the generic container of METHOD to CONTAINER.
1281 * LOCKING: Acquires the image lock.
1284 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1286 g_assert (method->is_generic);
1288 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1292 * mono_class_find_enum_basetype:
1293 * @class: The enum class
1295 * Determine the basetype of an enum by iterating through its fields. We do this
1296 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1299 mono_class_find_enum_basetype (MonoClass *klass, MonoError *error)
1301 MonoGenericContainer *container = NULL;
1302 MonoImage *m = klass->image;
1303 const int top = klass->field.count;
1306 g_assert (klass->enumtype);
1308 mono_error_init (error);
1310 if (klass->generic_container)
1311 container = klass->generic_container;
1312 else if (klass->generic_class) {
1313 MonoClass *gklass = klass->generic_class->container_class;
1315 container = gklass->generic_container;
1316 g_assert (container);
1320 * Fetch all the field information.
1322 for (i = 0; i < top; i++){
1324 guint32 cols [MONO_FIELD_SIZE];
1325 int idx = klass->field.first + i;
1328 /* klass->field.first and idx points into the fieldptr table */
1329 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1331 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1334 if (!mono_verifier_verify_field_signature (klass->image, cols [MONO_FIELD_SIGNATURE], NULL)) {
1335 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x", cols [MONO_FIELD_SIGNATURE]);
1339 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1340 mono_metadata_decode_value (sig, &sig);
1341 /* FIELD signature == 0x06 */
1343 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig);
1347 ftype = mono_metadata_parse_type_checked (m, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
1351 if (klass->generic_class) {
1352 //FIXME do we leak here?
1353 ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (klass), error);
1354 if (!mono_error_ok (error))
1356 ftype->attrs = cols [MONO_FIELD_FLAGS];
1361 mono_error_set_type_load_class (error, klass, "Could not find base type");
1368 * Checks for MonoClass::has_failure without resolving all MonoType's into MonoClass'es
1371 mono_type_has_exceptions (MonoType *type)
1373 switch (type->type) {
1374 case MONO_TYPE_CLASS:
1375 case MONO_TYPE_VALUETYPE:
1376 case MONO_TYPE_SZARRAY:
1377 return mono_class_has_failure (type->data.klass);
1378 case MONO_TYPE_ARRAY:
1379 return mono_class_has_failure (type->data.array->eklass);
1380 case MONO_TYPE_GENERICINST:
1381 return mono_class_has_failure (mono_generic_class_get_class (type->data.generic_class));
1388 mono_error_set_for_class_failure (MonoError *oerror, const MonoClass *klass)
1390 g_assert (mono_class_has_failure (klass));
1391 MonoErrorBoxed *box = (MonoErrorBoxed*)mono_class_get_exception_data (klass);
1392 mono_error_set_from_boxed (oerror, box);
1399 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1403 mono_class_alloc (MonoClass *klass, int size)
1405 if (klass->generic_class)
1406 return mono_image_set_alloc (klass->generic_class->owner, size);
1408 return mono_image_alloc (klass->image, size);
1412 mono_class_alloc0 (MonoClass *klass, int size)
1416 res = mono_class_alloc (klass, size);
1417 memset (res, 0, size);
1421 #define mono_class_new0(klass,struct_type, n_structs) \
1422 ((struct_type *) mono_class_alloc0 ((klass), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1425 * mono_class_setup_basic_field_info:
1426 * @class: The class to initialize
1428 * Initializes the klass->fields.
1429 * LOCKING: Assumes the loader lock is held.
1432 mono_class_setup_basic_field_info (MonoClass *klass)
1434 MonoClassField *field;
1442 gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
1443 image = klass->image;
1444 top = klass->field.count;
1446 if (klass->generic_class && image_is_dynamic (klass->generic_class->container_class->image) && !klass->generic_class->container_class->wastypebuilder) {
1448 * This happens when a generic instance of an unfinished generic typebuilder
1449 * is used as an element type for creating an array type. We can't initialize
1450 * the fields of this class using the fields of gklass, since gklass is not
1451 * finished yet, fields could be added to it later.
1457 mono_class_setup_basic_field_info (gtd);
1459 top = gtd->field.count;
1460 klass->field.first = gtd->field.first;
1461 klass->field.count = gtd->field.count;
1464 klass->fields = (MonoClassField *)mono_class_alloc0 (klass, sizeof (MonoClassField) * top);
1467 * Fetch all the field information.
1469 for (i = 0; i < top; i++){
1470 field = &klass->fields [i];
1471 field->parent = klass;
1474 field->name = mono_field_get_name (>d->fields [i]);
1476 int idx = klass->field.first + i;
1477 /* klass->field.first and idx points into the fieldptr table */
1478 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1479 /* The name is needed for fieldrefs */
1480 field->name = mono_metadata_string_heap (image, name_idx);
1486 * mono_class_set_failure_causedby_class:
1487 * @klass: the class that is failing
1488 * @caused_by: the class that caused the failure
1489 * @msg: Why @klass is failing.
1491 * If @caused_by has a failure, sets a TypeLoadException failure on
1492 * @klass with message "@msg, due to: {@caused_by message}".
1494 * Returns: TRUE if a failiure was set, or FALSE if @caused_by doesn't have a failure.
1497 mono_class_set_type_load_failure_causedby_class (MonoClass *klass, const MonoClass *caused_by, const gchar* msg)
1499 if (mono_class_has_failure (caused_by)) {
1500 MonoError cause_error;
1501 mono_error_init (&cause_error);
1502 mono_error_set_for_class_failure (&cause_error, caused_by);
1503 mono_class_set_type_load_failure (klass, "%s, due to: %s", msg, mono_error_get_message (&cause_error));
1504 mono_error_cleanup (&cause_error);
1513 * mono_class_setup_fields:
1514 * @class: The class to initialize
1516 * Initializes the klass->fields.
1517 * LOCKING: Assumes the loader lock is held.
1520 mono_class_setup_fields (MonoClass *klass)
1523 MonoImage *m = klass->image;
1525 guint32 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1526 int i, blittable = TRUE;
1527 guint32 real_size = 0;
1528 guint32 packing_size = 0;
1530 gboolean explicit_size;
1531 MonoClassField *field;
1532 MonoGenericContainer *container = NULL;
1533 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
1536 * FIXME: We have a race condition here. It's possible that this function returns
1537 * to its caller with `instance_size` set to `0` instead of the actual size. This
1538 * is not a problem when the function is called recursively on the same class,
1539 * because the size will be initialized by the outer invocation. What follows is a
1540 * description of how it can occur in other cases, too. There it is a problem,
1541 * because it can lead to the GC being asked to allocate an object of size `0`,
1542 * which SGen chokes on. The race condition is triggered infrequently by
1543 * `tests/sgen-suspend.cs`.
1545 * This function is called for a class whenever one of its subclasses is inited.
1546 * For example, it's called for every subclass of Object. What it does is this:
1548 * if (klass->setup_fields_called)
1551 * klass->instance_size = 0;
1553 * klass->setup_fields_called = 1;
1554 * ... critical point
1555 * klass->instance_size = actual_instance_size;
1557 * The last two steps are sometimes reversed, but that only changes the way in which
1558 * the race condition works.
1560 * Assume thread A goes through this function and makes it to the critical point.
1561 * Now thread B runs the function and, since `setup_fields_called` is set, returns
1562 * immediately, but `instance_size` is incorrect.
1564 * The other case looks like this:
1566 * if (klass->setup_fields_called)
1568 * ... critical point X
1569 * klass->instance_size = 0;
1570 * ... critical point Y
1571 * klass->instance_size = actual_instance_size;
1573 * klass->setup_fields_called = 1;
1575 * Assume thread A goes through the function and makes it to critical point X. Now
1576 * thread B runs through the whole of the function, returning, assuming
1577 * `instance_size` is set. At that point thread A gets to run and makes it to
1578 * critical point Y, at which time `instance_size` is `0` again, invalidating thread
1581 if (klass->setup_fields_called)
1584 if (klass->generic_class && image_is_dynamic (klass->generic_class->container_class->image) && !klass->generic_class->container_class->wastypebuilder) {
1586 * This happens when a generic instance of an unfinished generic typebuilder
1587 * is used as an element type for creating an array type. We can't initialize
1588 * the fields of this class using the fields of gklass, since gklass is not
1589 * finished yet, fields could be added to it later.
1594 mono_class_setup_basic_field_info (klass);
1595 top = klass->field.count;
1598 mono_class_setup_fields (gtd);
1599 if (mono_class_set_type_load_failure_causedby_class (klass, gtd, "Generic type definition failed"))
1605 klass->sizes.class_size = 0;
1607 if (klass->parent) {
1608 /* For generic instances, klass->parent might not have been initialized */
1609 mono_class_init (klass->parent);
1610 if (!klass->parent->size_inited) {
1611 mono_class_setup_fields (klass->parent);
1612 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Could not set up parent class"))
1615 instance_size += klass->parent->instance_size;
1616 klass->min_align = klass->parent->min_align;
1617 /* we use |= since it may have been set already */
1618 klass->has_references |= klass->parent->has_references;
1619 blittable = klass->parent->blittable;
1621 instance_size = sizeof (MonoObject);
1622 klass->min_align = 1;
1625 /* We can't really enable 16 bytes alignment until the GC supports it.
1626 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1627 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1628 Bug #506144 is an example of this issue.
1630 if (klass->simd_type)
1631 klass->min_align = 16;
1633 /* Get the real size */
1634 explicit_size = mono_metadata_packing_from_typedef (klass->image, klass->type_token, &packing_size, &real_size);
1636 if (explicit_size) {
1637 if ((packing_size & 0xffffff00) != 0) {
1638 mono_class_set_type_load_failure (klass, "Could not load struct '%s' with packing size %d >= 256", klass->name, packing_size);
1641 klass->packing_size = packing_size;
1642 real_size += instance_size;
1646 if (explicit_size && real_size) {
1647 instance_size = MAX (real_size, instance_size);
1649 klass->blittable = blittable;
1650 if (!klass->instance_size)
1651 klass->instance_size = instance_size;
1652 mono_memory_barrier ();
1653 klass->size_inited = 1;
1654 klass->fields_inited = 1;
1655 klass->setup_fields_called = 1;
1659 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(mono_is_corlib_image (klass->image) && !strcmp (klass->name_space, "System") && !strcmp (klass->name, "ValueType")))
1662 /* Prevent infinite loops if the class references itself */
1663 klass->setup_fields_called = 1;
1665 if (klass->generic_container) {
1666 container = klass->generic_container;
1668 container = gtd->generic_container;
1669 g_assert (container);
1673 * Fetch all the field information.
1675 for (i = 0; i < top; i++){
1676 int idx = klass->field.first + i;
1677 field = &klass->fields [i];
1679 field->parent = klass;
1682 mono_field_resolve_type (field, &error);
1683 if (!mono_error_ok (&error)) {
1684 /*mono_field_resolve_type already failed class*/
1685 mono_error_cleanup (&error);
1689 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(klass), field->name);
1690 g_assert (field->type);
1693 if (mono_field_is_deleted (field))
1696 MonoClassField *gfield = >d->fields [i];
1697 field->offset = gfield->offset;
1699 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1701 mono_metadata_field_info (m, idx, &offset, NULL, NULL);
1702 field->offset = offset;
1704 if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1705 mono_class_set_type_load_failure (klass, "Missing field layout info for %s", field->name);
1708 if (field->offset < -1) { /*-1 is used to encode special static fields */
1709 mono_class_set_type_load_failure (klass, "Field '%s' has a negative offset %d", field->name, field->offset);
1712 if (klass->generic_container) {
1713 mono_class_set_type_load_failure (klass, "Generic class cannot have explicit layout.");
1719 /* Only do these checks if we still think this type is blittable */
1720 if (blittable && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1721 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1724 MonoClass *field_class = mono_class_from_mono_type (field->type);
1726 mono_class_setup_fields (field_class);
1727 if (mono_class_has_failure (field_class)) {
1728 MonoError field_error;
1729 mono_error_init (&field_error);
1730 mono_error_set_for_class_failure (&field_error, field_class);
1731 mono_class_set_type_load_failure (klass, "Could not set up field '%s' due to: %s", field->name, mono_error_get_message (&field_error));
1732 mono_error_cleanup (&field_error);
1736 if (!field_class || !field_class->blittable)
1741 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1742 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
1743 blittable = klass->element_class->blittable;
1746 if (mono_type_has_exceptions (field->type)) {
1747 char *class_name = mono_type_get_full_name (klass);
1748 char *type_name = mono_type_full_name (field->type);
1750 mono_class_set_type_load_failure (klass, "");
1751 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1752 g_free (class_name);
1756 /* The def_value of fields is compute lazily during vtable creation */
1759 if (klass == mono_defaults.string_class)
1762 klass->blittable = blittable;
1764 if (klass->enumtype && !mono_class_enum_basetype (klass)) {
1765 mono_class_set_type_load_failure (klass, "The enumeration's base type is invalid.");
1768 if (explicit_size && real_size) {
1769 instance_size = MAX (real_size, instance_size);
1772 if (mono_class_has_failure (klass))
1774 mono_class_layout_fields (klass, instance_size);
1776 /*valuetypes can't be neither bigger than 1Mb or empty. */
1777 if (klass->valuetype && (klass->instance_size <= 0 || klass->instance_size > (0x100000 + sizeof (MonoObject))))
1778 mono_class_set_type_load_failure (klass, "Value type instance size (%d) cannot be zero, negative, or bigger than 1Mb", klass->instance_size);
1780 mono_memory_barrier ();
1781 klass->fields_inited = 1;
1785 * mono_class_setup_fields_locking:
1786 * @class: The class to initialize
1788 * Initializes the klass->fields array of fields.
1789 * Aquires the loader lock.
1792 mono_class_setup_fields_locking (MonoClass *klass)
1794 /* This can be checked without locks */
1795 if (klass->fields_inited)
1797 mono_loader_lock ();
1798 mono_class_setup_fields (klass);
1799 mono_loader_unlock ();
1803 * mono_class_has_references:
1805 * Returns whenever @klass->has_references is set, initializing it if needed.
1806 * Aquires the loader lock.
1809 mono_class_has_references (MonoClass *klass)
1811 if (klass->init_pending) {
1812 /* Be conservative */
1815 mono_class_init (klass);
1817 return klass->has_references;
1822 * mono_type_get_basic_type_from_generic:
1825 * Returns a closed type corresponding to the possibly open type
1829 mono_type_get_basic_type_from_generic (MonoType *type)
1831 /* When we do generic sharing we let type variables stand for reference/primitive types. */
1832 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) &&
1833 (!type->data.generic_param->gshared_constraint || type->data.generic_param->gshared_constraint->type == MONO_TYPE_OBJECT))
1834 return &mono_defaults.object_class->byval_arg;
1839 type_has_references (MonoClass *klass, MonoType *ftype)
1841 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)))))
1843 if (!ftype->byref && (ftype->type == MONO_TYPE_VAR || ftype->type == MONO_TYPE_MVAR)) {
1844 MonoGenericParam *gparam = ftype->data.generic_param;
1846 if (gparam->gshared_constraint)
1847 return mono_class_has_references (mono_class_from_mono_type (gparam->gshared_constraint));
1853 * mono_class_layout_fields:
1855 * @instance_size: base instance size
1857 * Compute the placement of fields inside an object or struct, according to
1858 * the layout rules and set the following fields in @class:
1859 * - has_references (if the class contains instance references firled or structs that contain references)
1860 * - has_static_refs (same, but for static fields)
1861 * - instance_size (size of the object in memory)
1862 * - class_size (size needed for the static fields)
1863 * - size_inited (flag set when the instance_size is set)
1865 * LOCKING: this is supposed to be called with the loader lock held.
1868 mono_class_layout_fields (MonoClass *klass, int instance_size)
1871 const int top = klass->field.count;
1872 guint32 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1873 guint32 pass, passes, real_size;
1874 gboolean gc_aware_layout = FALSE;
1875 gboolean has_static_fields = FALSE;
1876 MonoClassField *field;
1879 * When we do generic sharing we need to have layout
1880 * information for open generic classes (either with a generic
1881 * context containing type variables or with a generic
1882 * container), so we don't return in that case anymore.
1886 * Enable GC aware auto layout: in this mode, reference
1887 * fields are grouped together inside objects, increasing collector
1889 * Requires that all classes whose layout is known to native code be annotated
1890 * with [StructLayout (LayoutKind.Sequential)]
1891 * Value types have gc_aware_layout disabled by default, as per
1892 * what the default is for other runtimes.
1894 /* corlib is missing [StructLayout] directives in many places */
1895 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1896 if (!klass->valuetype)
1897 gc_aware_layout = TRUE;
1900 /* Compute klass->has_references */
1902 * Process non-static fields first, since static fields might recursively
1903 * refer to the class itself.
1905 for (i = 0; i < top; i++) {
1908 field = &klass->fields [i];
1910 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1911 ftype = mono_type_get_underlying_type (field->type);
1912 ftype = mono_type_get_basic_type_from_generic (ftype);
1913 if (type_has_references (klass, ftype))
1914 klass->has_references = TRUE;
1918 for (i = 0; i < top; i++) {
1921 field = &klass->fields [i];
1923 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1924 ftype = mono_type_get_underlying_type (field->type);
1925 ftype = mono_type_get_basic_type_from_generic (ftype);
1926 if (type_has_references (klass, ftype))
1927 klass->has_static_refs = TRUE;
1931 for (i = 0; i < top; i++) {
1934 field = &klass->fields [i];
1936 ftype = mono_type_get_underlying_type (field->type);
1937 ftype = mono_type_get_basic_type_from_generic (ftype);
1938 if (type_has_references (klass, ftype)) {
1939 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1940 klass->has_static_refs = TRUE;
1942 klass->has_references = TRUE;
1947 * Compute field layout and total size (not considering static fields)
1950 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1951 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1953 if (gc_aware_layout)
1958 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1961 if (klass->parent) {
1962 mono_class_setup_fields (klass->parent);
1963 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Cannot initialize parent class"))
1965 real_size = klass->parent->instance_size;
1967 real_size = sizeof (MonoObject);
1970 for (pass = 0; pass < passes; ++pass) {
1971 for (i = 0; i < top; i++){
1976 field = &klass->fields [i];
1978 if (mono_field_is_deleted (field))
1980 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1983 ftype = mono_type_get_underlying_type (field->type);
1984 ftype = mono_type_get_basic_type_from_generic (ftype);
1985 if (gc_aware_layout) {
1986 if (type_has_references (klass, ftype)) {
1995 if ((top == 1) && (klass->instance_size == sizeof (MonoObject)) &&
1996 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1997 /* This field is a hack inserted by MCS to empty structures */
2001 size = mono_type_size (field->type, &align);
2003 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
2004 align = klass->packing_size ? MIN (klass->packing_size, align): align;
2005 /* if the field has managed references, we need to force-align it
2008 if (type_has_references (klass, ftype))
2009 align = MAX (align, sizeof (gpointer));
2011 klass->min_align = MAX (align, klass->min_align);
2012 field->offset = real_size;
2014 field->offset += align - 1;
2015 field->offset &= ~(align - 1);
2017 /*TypeBuilders produce all sort of weird things*/
2018 g_assert (image_is_dynamic (klass->image) || field->offset > 0);
2019 real_size = field->offset + size;
2022 instance_size = MAX (real_size, instance_size);
2024 if (instance_size & (klass->min_align - 1)) {
2025 instance_size += klass->min_align - 1;
2026 instance_size &= ~(klass->min_align - 1);
2030 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
2034 for (i = 0; i < top; i++) {
2039 field = &klass->fields [i];
2042 * There must be info about all the fields in a type if it
2043 * uses explicit layout.
2045 if (mono_field_is_deleted (field))
2047 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2050 size = mono_type_size (field->type, &align);
2051 align = klass->packing_size ? MIN (klass->packing_size, align): align;
2052 klass->min_align = MAX (align, klass->min_align);
2055 * When we get here, field->offset is already set by the
2056 * loader (for either runtime fields or fields loaded from metadata).
2057 * The offset is from the start of the object: this works for both
2058 * classes and valuetypes.
2060 field->offset += sizeof (MonoObject);
2061 ftype = mono_type_get_underlying_type (field->type);
2062 ftype = mono_type_get_basic_type_from_generic (ftype);
2063 if (type_has_references (klass, ftype)) {
2064 if (field->offset % sizeof (gpointer)) {
2065 mono_class_set_type_load_failure (klass, "Reference typed field '%s' has explicit offset that is not pointer-size aligned.", field->name);
2072 real_size = MAX (real_size, size + field->offset);
2075 if (klass->has_references) {
2076 ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
2078 /* Check for overlapping reference and non-reference fields */
2079 for (i = 0; i < top; i++) {
2082 field = &klass->fields [i];
2084 if (mono_field_is_deleted (field))
2086 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2088 ftype = mono_type_get_underlying_type (field->type);
2089 if (MONO_TYPE_IS_REFERENCE (ftype))
2090 ref_bitmap [field->offset / sizeof (gpointer)] = 1;
2092 for (i = 0; i < top; i++) {
2093 field = &klass->fields [i];
2095 if (mono_field_is_deleted (field))
2097 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2100 // FIXME: Too much code does this
2102 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field->offset / sizeof (gpointer)]) {
2103 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);
2107 g_free (ref_bitmap);
2110 instance_size = MAX (real_size, instance_size);
2111 if (instance_size & (klass->min_align - 1)) {
2112 instance_size += klass->min_align - 1;
2113 instance_size &= ~(klass->min_align - 1);
2119 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2121 * This leads to all kinds of problems with nested structs, so only
2122 * enable it when a MONO_DEBUG property is set.
2124 * For small structs, set min_align to at least the struct size to improve
2125 * performance, and since the JIT memset/memcpy code assumes this and generates
2126 * unaligned accesses otherwise. See #78990 for a testcase.
2128 if (mono_align_small_structs) {
2129 if (instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2130 klass->min_align = MAX (klass->min_align, instance_size - sizeof (MonoObject));
2134 if (klass->instance_size && !klass->image->dynamic) {
2135 /* Might be already set using cached info */
2136 g_assert (klass->instance_size == instance_size);
2138 klass->instance_size = instance_size;
2140 mono_memory_barrier ();
2141 klass->size_inited = 1;
2144 * Compute static field layout and size
2146 for (i = 0; i < top; i++){
2150 field = &klass->fields [i];
2152 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2154 if (mono_field_is_deleted (field))
2157 if (mono_type_has_exceptions (field->type)) {
2158 mono_class_set_type_load_failure (klass, "Field '%s' has an invalid type.", field->name);
2162 has_static_fields = TRUE;
2164 size = mono_type_size (field->type, &align);
2165 field->offset = klass->sizes.class_size;
2166 /*align is always non-zero here*/
2167 field->offset += align - 1;
2168 field->offset &= ~(align - 1);
2169 klass->sizes.class_size = field->offset + size;
2172 if (has_static_fields && klass->sizes.class_size == 0)
2173 /* Simplify code which depends on class_size != 0 if the class has static fields */
2174 klass->sizes.class_size = 8;
2178 create_array_method (MonoClass *klass, const char *name, MonoMethodSignature *sig)
2182 method = (MonoMethod *) mono_image_alloc0 (klass->image, sizeof (MonoMethodPInvoke));
2183 method->klass = klass;
2184 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2185 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2186 method->signature = sig;
2187 method->name = name;
2190 if (name [0] == '.') {
2191 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2193 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2199 * mono_class_setup_methods:
2202 * Initializes the 'methods' array in CLASS.
2203 * Calling this method should be avoided if possible since it allocates a lot
2204 * of long-living MonoMethod structures.
2205 * Methods belonging to an interface are assigned a sequential slot starting
2208 * On failure this function sets klass->has_failure and stores a MonoErrorBoxed with details
2211 mono_class_setup_methods (MonoClass *klass)
2214 MonoMethod **methods;
2219 if (klass->generic_class) {
2221 MonoClass *gklass = klass->generic_class->container_class;
2223 mono_class_init (gklass);
2224 if (!mono_class_has_failure (gklass))
2225 mono_class_setup_methods (gklass);
2226 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2229 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2230 count = gklass->method.count;
2231 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * (count + 1));
2233 for (i = 0; i < count; i++) {
2234 methods [i] = mono_class_inflate_generic_method_full_checked (
2235 gklass->methods [i], klass, mono_class_get_context (klass), &error);
2236 if (!mono_error_ok (&error)) {
2237 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2238 mono_class_set_type_load_failure (klass, "Could not inflate method %s due to %s", method, mono_error_get_message (&error));
2241 mono_error_cleanup (&error);
2245 } else if (klass->rank) {
2247 MonoMethod *amethod;
2248 MonoMethodSignature *sig;
2249 int count_generic = 0, first_generic = 0;
2251 gboolean jagged_ctor = FALSE;
2253 count = 3 + (klass->rank > 1? 2: 1);
2255 mono_class_setup_interfaces (klass, &error);
2256 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2258 if (klass->rank == 1 && klass->element_class->rank) {
2260 klass->method.count ++;
2263 if (klass->interface_count) {
2264 count_generic = generic_array_methods (klass);
2265 first_generic = count;
2266 count += klass->interface_count * count_generic;
2269 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * count);
2271 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2272 sig->ret = &mono_defaults.void_class->byval_arg;
2273 sig->pinvoke = TRUE;
2274 sig->hasthis = TRUE;
2275 for (i = 0; i < klass->rank; ++i)
2276 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2278 amethod = create_array_method (klass, ".ctor", sig);
2279 methods [method_num++] = amethod;
2280 if (klass->rank > 1) {
2281 sig = mono_metadata_signature_alloc (klass->image, klass->rank * 2);
2282 sig->ret = &mono_defaults.void_class->byval_arg;
2283 sig->pinvoke = TRUE;
2284 sig->hasthis = TRUE;
2285 for (i = 0; i < klass->rank * 2; ++i)
2286 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2288 amethod = create_array_method (klass, ".ctor", sig);
2289 methods [method_num++] = amethod;
2293 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2294 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2295 sig->ret = &mono_defaults.void_class->byval_arg;
2296 sig->pinvoke = TRUE;
2297 sig->hasthis = TRUE;
2298 for (i = 0; i < klass->rank + 1; ++i)
2299 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2300 amethod = create_array_method (klass, ".ctor", sig);
2301 methods [method_num++] = amethod;
2304 /* element Get (idx11, [idx2, ...]) */
2305 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2306 sig->ret = &klass->element_class->byval_arg;
2307 sig->pinvoke = TRUE;
2308 sig->hasthis = TRUE;
2309 for (i = 0; i < klass->rank; ++i)
2310 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2311 amethod = create_array_method (klass, "Get", sig);
2312 methods [method_num++] = amethod;
2313 /* element& Address (idx11, [idx2, ...]) */
2314 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2315 sig->ret = &klass->element_class->this_arg;
2316 sig->pinvoke = TRUE;
2317 sig->hasthis = TRUE;
2318 for (i = 0; i < klass->rank; ++i)
2319 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2320 amethod = create_array_method (klass, "Address", sig);
2321 methods [method_num++] = amethod;
2322 /* void Set (idx11, [idx2, ...], element) */
2323 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2324 sig->ret = &mono_defaults.void_class->byval_arg;
2325 sig->pinvoke = TRUE;
2326 sig->hasthis = TRUE;
2327 for (i = 0; i < klass->rank; ++i)
2328 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2329 sig->params [i] = &klass->element_class->byval_arg;
2330 amethod = create_array_method (klass, "Set", sig);
2331 methods [method_num++] = amethod;
2333 for (i = 0; i < klass->interface_count; i++)
2334 setup_generic_array_ifaces (klass, klass->interfaces [i], methods, first_generic + i * count_generic);
2338 count = klass->method.count;
2339 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * count);
2340 for (i = 0; i < count; ++i) {
2341 int idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_METHOD, klass->method.first + i + 1);
2342 methods [i] = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | idx, klass, NULL, &error);
2344 mono_class_set_type_load_failure (klass, "Could not load method %d due to %s", i, mono_error_get_message (&error));
2345 mono_error_cleanup (&error);
2350 if (MONO_CLASS_IS_INTERFACE (klass)) {
2352 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2353 for (i = 0; i < count; ++i) {
2354 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2355 methods [i]->slot = slot++;
2359 mono_image_lock (klass->image);
2361 if (!klass->methods) {
2362 klass->method.count = count;
2364 /* Needed because of the double-checking locking pattern */
2365 mono_memory_barrier ();
2367 klass->methods = methods;
2370 mono_image_unlock (klass->image);
2374 * mono_class_get_method_by_index:
2376 * Returns klass->methods [index], initializing klass->methods if neccesary.
2378 * LOCKING: Acquires the loader lock.
2381 mono_class_get_method_by_index (MonoClass *klass, int index)
2384 /* Avoid calling setup_methods () if possible */
2385 if (klass->generic_class && !klass->methods) {
2386 MonoClass *gklass = klass->generic_class->container_class;
2389 m = mono_class_inflate_generic_method_full_checked (
2390 gklass->methods [index], klass, mono_class_get_context (klass), &error);
2391 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2393 * If setup_methods () is called later for this class, no duplicates are created,
2394 * since inflate_generic_method guarantees that only one instance of a method
2395 * is created for each context.
2398 mono_class_setup_methods (klass);
2399 g_assert (m == klass->methods [index]);
2403 mono_class_setup_methods (klass);
2404 if (mono_class_has_failure (klass)) /*FIXME do proper error handling*/
2406 g_assert (index >= 0 && index < klass->method.count);
2407 return klass->methods [index];
2412 * mono_class_get_inflated_method:
2414 * Given an inflated class CLASS and a method METHOD which should be a method of
2415 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2418 mono_class_get_inflated_method (MonoClass *klass, MonoMethod *method)
2420 MonoClass *gklass = klass->generic_class->container_class;
2423 g_assert (method->klass == gklass);
2425 mono_class_setup_methods (gklass);
2426 g_assert (!mono_class_has_failure (gklass)); /*FIXME do proper error handling*/
2428 for (i = 0; i < gklass->method.count; ++i) {
2429 if (gklass->methods [i] == method) {
2430 if (klass->methods) {
2431 return klass->methods [i];
2434 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], klass, mono_class_get_context (klass), &error);
2435 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2445 * mono_class_get_vtable_entry:
2447 * Returns klass->vtable [offset], computing it if neccesary. Returns NULL on failure.
2448 * LOCKING: Acquires the loader lock.
2451 mono_class_get_vtable_entry (MonoClass *klass, int offset)
2455 if (klass->rank == 1) {
2457 * szarrays do not overwrite any methods of Array, so we can avoid
2458 * initializing their vtables in some cases.
2460 mono_class_setup_vtable (klass->parent);
2461 if (offset < klass->parent->vtable_size)
2462 return klass->parent->vtable [offset];
2465 if (klass->generic_class) {
2467 MonoClass *gklass = klass->generic_class->container_class;
2468 mono_class_setup_vtable (gklass);
2469 m = gklass->vtable [offset];
2471 m = mono_class_inflate_generic_method_full_checked (m, klass, mono_class_get_context (klass), &error);
2472 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2474 mono_class_setup_vtable (klass);
2475 if (mono_class_has_failure (klass))
2477 m = klass->vtable [offset];
2484 * mono_class_get_vtable_size:
2486 * Return the vtable size for KLASS.
2489 mono_class_get_vtable_size (MonoClass *klass)
2491 mono_class_setup_vtable (klass);
2493 return klass->vtable_size;
2497 * mono_class_setup_properties:
2499 * Initialize klass->ext.property and klass->ext.properties.
2501 * This method can fail the class.
2504 mono_class_setup_properties (MonoClass *klass)
2506 guint startm, endm, i, j;
2507 guint32 cols [MONO_PROPERTY_SIZE];
2508 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2509 MonoProperty *properties;
2513 if (klass->ext && klass->ext->properties)
2516 if (klass->generic_class) {
2517 MonoClass *gklass = klass->generic_class->container_class;
2519 mono_class_init (gklass);
2520 mono_class_setup_properties (gklass);
2521 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2524 properties = mono_class_new0 (klass, MonoProperty, gklass->ext->property.count + 1);
2526 for (i = 0; i < gklass->ext->property.count; i++) {
2528 MonoProperty *prop = &properties [i];
2530 *prop = gklass->ext->properties [i];
2533 prop->get = mono_class_inflate_generic_method_full_checked (
2534 prop->get, klass, mono_class_get_context (klass), &error);
2536 prop->set = mono_class_inflate_generic_method_full_checked (
2537 prop->set, klass, mono_class_get_context (klass), &error);
2539 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2540 prop->parent = klass;
2543 first = gklass->ext->property.first;
2544 count = gklass->ext->property.count;
2546 first = mono_metadata_properties_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2547 count = last - first;
2550 mono_class_setup_methods (klass);
2551 if (mono_class_has_failure (klass))
2555 properties = (MonoProperty *)mono_class_alloc0 (klass, sizeof (MonoProperty) * count);
2556 for (i = first; i < last; ++i) {
2557 mono_metadata_decode_table_row (klass->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2558 properties [i - first].parent = klass;
2559 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2560 properties [i - first].name = mono_metadata_string_heap (klass->image, cols [MONO_PROPERTY_NAME]);
2562 startm = mono_metadata_methods_from_property (klass->image, i, &endm);
2563 for (j = startm; j < endm; ++j) {
2566 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2568 if (klass->image->uncompressed_metadata) {
2570 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2571 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2572 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2574 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - klass->method.first];
2577 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2578 case METHOD_SEMANTIC_SETTER:
2579 properties [i - first].set = method;
2581 case METHOD_SEMANTIC_GETTER:
2582 properties [i - first].get = method;
2591 mono_class_alloc_ext (klass);
2593 mono_image_lock (klass->image);
2595 if (klass->ext->properties) {
2596 /* We leak 'properties' which was allocated from the image mempool */
2597 mono_image_unlock (klass->image);
2601 klass->ext->property.first = first;
2602 klass->ext->property.count = count;
2604 /* Flush any pending writes as we do double checked locking on klass->ext->properties */
2605 mono_memory_barrier ();
2607 /* Leave this assignment as the last op in the function */
2608 klass->ext->properties = properties;
2610 mono_image_unlock (klass->image);
2614 inflate_method_listz (MonoMethod **methods, MonoClass *klass, MonoGenericContext *context)
2616 MonoMethod **om, **retval;
2619 for (om = methods, count = 0; *om; ++om, ++count)
2622 retval = g_new0 (MonoMethod*, count + 1);
2624 for (om = methods, count = 0; *om; ++om, ++count) {
2626 retval [count] = mono_class_inflate_generic_method_full_checked (*om, klass, context, &error);
2627 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2633 /*This method can fail the class.*/
2635 mono_class_setup_events (MonoClass *klass)
2638 guint startm, endm, i, j;
2639 guint32 cols [MONO_EVENT_SIZE];
2640 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2644 if (klass->ext && klass->ext->events)
2647 if (klass->generic_class) {
2648 MonoClass *gklass = klass->generic_class->container_class;
2649 MonoGenericContext *context = NULL;
2651 mono_class_setup_events (gklass);
2652 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2655 first = gklass->ext->event.first;
2656 count = gklass->ext->event.count;
2658 events = mono_class_new0 (klass, MonoEvent, count);
2661 context = mono_class_get_context (klass);
2663 for (i = 0; i < count; i++) {
2665 MonoEvent *event = &events [i];
2666 MonoEvent *gevent = &gklass->ext->events [i];
2668 mono_error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2670 event->parent = klass;
2671 event->name = gevent->name;
2672 event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, klass, context, &error) : NULL;
2673 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2674 event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, klass, context, &error) : NULL;
2675 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2676 event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, klass, context, &error) : NULL;
2677 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2679 #ifndef MONO_SMALL_CONFIG
2680 event->other = gevent->other ? inflate_method_listz (gevent->other, klass, context) : NULL;
2682 event->attrs = gevent->attrs;
2685 first = mono_metadata_events_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2686 count = last - first;
2689 mono_class_setup_methods (klass);
2690 if (mono_class_has_failure (klass)) {
2695 events = (MonoEvent *)mono_class_alloc0 (klass, sizeof (MonoEvent) * count);
2696 for (i = first; i < last; ++i) {
2697 MonoEvent *event = &events [i - first];
2699 mono_metadata_decode_table_row (klass->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2700 event->parent = klass;
2701 event->attrs = cols [MONO_EVENT_FLAGS];
2702 event->name = mono_metadata_string_heap (klass->image, cols [MONO_EVENT_NAME]);
2704 startm = mono_metadata_methods_from_event (klass->image, i, &endm);
2705 for (j = startm; j < endm; ++j) {
2708 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2710 if (klass->image->uncompressed_metadata) {
2712 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2713 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2714 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2716 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - klass->method.first];
2719 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2720 case METHOD_SEMANTIC_ADD_ON:
2721 event->add = method;
2723 case METHOD_SEMANTIC_REMOVE_ON:
2724 event->remove = method;
2726 case METHOD_SEMANTIC_FIRE:
2727 event->raise = method;
2729 case METHOD_SEMANTIC_OTHER: {
2730 #ifndef MONO_SMALL_CONFIG
2733 if (event->other == NULL) {
2734 event->other = g_new0 (MonoMethod*, 2);
2736 while (event->other [n])
2738 event->other = (MonoMethod **)g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2740 event->other [n] = method;
2741 /* NULL terminated */
2742 event->other [n + 1] = NULL;
2753 mono_class_alloc_ext (klass);
2755 mono_image_lock (klass->image);
2757 if (klass->ext->events) {
2758 mono_image_unlock (klass->image);
2762 klass->ext->event.first = first;
2763 klass->ext->event.count = count;
2765 /* Flush any pending writes as we do double checked locking on klass->ext.events */
2766 mono_memory_barrier ();
2768 /* Leave this assignment as the last op in the function */
2769 klass->ext->events = events;
2771 mono_image_unlock (klass->image);
2775 * Global pool of interface IDs, represented as a bitset.
2776 * LOCKING: Protected by the classes lock.
2778 static MonoBitSet *global_interface_bitset = NULL;
2781 * mono_unload_interface_ids:
2782 * @bitset: bit set of interface IDs
2784 * When an image is unloaded, the interface IDs associated with
2785 * the image are put back in the global pool of IDs so the numbers
2789 mono_unload_interface_ids (MonoBitSet *bitset)
2792 mono_bitset_sub (global_interface_bitset, bitset);
2797 mono_unload_interface_id (MonoClass *klass)
2799 if (global_interface_bitset && klass->interface_id) {
2801 mono_bitset_clear (global_interface_bitset, klass->interface_id);
2807 * mono_get_unique_iid:
2810 * Assign a unique integer ID to the interface represented by @class.
2811 * The ID will positive and as small as possible.
2812 * LOCKING: Acquires the classes lock.
2813 * Returns: The new ID.
2816 mono_get_unique_iid (MonoClass *klass)
2820 g_assert (MONO_CLASS_IS_INTERFACE (klass));
2824 if (!global_interface_bitset) {
2825 global_interface_bitset = mono_bitset_new (128, 0);
2828 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2830 int old_size = mono_bitset_size (global_interface_bitset);
2831 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2832 mono_bitset_free (global_interface_bitset);
2833 global_interface_bitset = new_set;
2836 mono_bitset_set (global_interface_bitset, iid);
2837 /* set the bit also in the per-image set */
2838 if (!klass->generic_class) {
2839 if (klass->image->interface_bitset) {
2840 if (iid >= mono_bitset_size (klass->image->interface_bitset)) {
2841 MonoBitSet *new_set = mono_bitset_clone (klass->image->interface_bitset, iid + 1);
2842 mono_bitset_free (klass->image->interface_bitset);
2843 klass->image->interface_bitset = new_set;
2846 klass->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2848 mono_bitset_set (klass->image->interface_bitset, iid);
2853 #ifndef MONO_SMALL_CONFIG
2854 if (mono_print_vtable) {
2856 char *type_name = mono_type_full_name (&klass->byval_arg);
2857 if (klass->generic_class && !klass->generic_class->context.class_inst->is_open) {
2858 generic_id = klass->generic_class->context.class_inst->id;
2859 g_assert (generic_id != 0);
2863 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, klass->image->name, type_name, generic_id);
2868 g_assert (iid <= 65535);
2873 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2878 mono_class_setup_interfaces (klass, error);
2879 return_if_nok (error);
2881 for (i = 0; i < klass->interface_count; i++) {
2882 ic = klass->interfaces [i];
2885 *res = g_ptr_array_new ();
2886 g_ptr_array_add (*res, ic);
2887 mono_class_init (ic);
2888 if (mono_class_has_failure (ic)) {
2889 mono_error_set_type_load_class (error, ic, "Error Loading class");
2893 collect_implemented_interfaces_aux (ic, res, error);
2894 return_if_nok (error);
2899 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2901 GPtrArray *res = NULL;
2903 collect_implemented_interfaces_aux (klass, &res, error);
2904 if (!mono_error_ok (error)) {
2906 g_ptr_array_free (res, TRUE);
2913 compare_interface_ids (const void *p_key, const void *p_element) {
2914 const MonoClass *key = (const MonoClass *)p_key;
2915 const MonoClass *element = *(const MonoClass **)p_element;
2917 return (key->interface_id - element->interface_id);
2920 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2922 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2923 MonoClass **result = (MonoClass **)mono_binary_search (
2925 klass->interfaces_packed,
2926 klass->interface_offsets_count,
2927 sizeof (MonoClass *),
2928 compare_interface_ids);
2930 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2937 * mono_class_interface_offset_with_variance:
2939 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2940 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2942 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2944 * FIXME figure out MS disambiguation rules and fix this function.
2947 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2948 int i = mono_class_interface_offset (klass, itf);
2949 *non_exact_match = FALSE;
2953 if (!mono_class_has_variant_generic_params (itf))
2956 for (i = 0; i < klass->interface_offsets_count; i++) {
2957 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2958 *non_exact_match = TRUE;
2959 return klass->interface_offsets_packed [i];
2967 print_implemented_interfaces (MonoClass *klass) {
2970 GPtrArray *ifaces = NULL;
2972 int ancestor_level = 0;
2974 name = mono_type_get_full_name (klass);
2975 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2978 for (i = 0; i < klass->interface_offsets_count; i++)
2979 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2980 klass->interfaces_packed [i]->interface_id,
2981 klass->interface_offsets_packed [i],
2982 klass->interfaces_packed [i]->method.count,
2983 klass->interfaces_packed [i]->name_space,
2984 klass->interfaces_packed [i]->name );
2985 printf ("Interface flags: ");
2986 for (i = 0; i <= klass->max_interface_id; i++)
2987 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2988 printf ("(%d,T)", i);
2990 printf ("(%d,F)", i);
2992 printf ("Dump interface flags:");
2993 #ifdef COMPRESSED_INTERFACE_BITMAP
2995 const uint8_t* p = klass->interface_bitmap;
2996 i = klass->max_interface_id;
2998 printf (" %d x 00 %02X", p [0], p [1]);
3004 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
3005 printf (" %02X", klass->interface_bitmap [i]);
3008 while (klass != NULL) {
3009 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
3010 ifaces = mono_class_get_implemented_interfaces (klass, &error);
3011 if (!mono_error_ok (&error)) {
3012 printf (" Type failed due to %s\n", mono_error_get_message (&error));
3013 mono_error_cleanup (&error);
3014 } else if (ifaces) {
3015 for (i = 0; i < ifaces->len; i++) {
3016 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3017 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
3018 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3020 mono_class_interface_offset (klass, ic),
3025 g_ptr_array_free (ifaces, TRUE);
3028 klass = klass->parent;
3033 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
3036 args [0] = &arg0->byval_arg;
3038 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
3042 array_class_get_if_rank (MonoClass *klass, guint rank)
3044 return rank ? mono_array_class_get (klass, rank) : klass;
3048 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
3050 valuetype_types [0] = eclass;
3051 if (eclass == mono_defaults.int16_class)
3052 valuetype_types [1] = mono_defaults.uint16_class;
3053 else if (eclass == mono_defaults.uint16_class)
3054 valuetype_types [1] = mono_defaults.int16_class;
3055 else if (eclass == mono_defaults.int32_class)
3056 valuetype_types [1] = mono_defaults.uint32_class;
3057 else if (eclass == mono_defaults.uint32_class)
3058 valuetype_types [1] = mono_defaults.int32_class;
3059 else if (eclass == mono_defaults.int64_class)
3060 valuetype_types [1] = mono_defaults.uint64_class;
3061 else if (eclass == mono_defaults.uint64_class)
3062 valuetype_types [1] = mono_defaults.int64_class;
3063 else if (eclass == mono_defaults.byte_class)
3064 valuetype_types [1] = mono_defaults.sbyte_class;
3065 else if (eclass == mono_defaults.sbyte_class)
3066 valuetype_types [1] = mono_defaults.byte_class;
3067 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
3068 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
3071 /* this won't be needed once bug #325495 is completely fixed
3072 * though we'll need something similar to know which interfaces to allow
3073 * in arrays when they'll be lazyly created
3075 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
3076 * MS returns diferrent types based on which instance is called. For example:
3077 * object obj = new byte[10][];
3078 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
3079 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
3082 * Fixing this should kill quite some code, save some bits and improve compatibility.
3085 get_implicit_generic_array_interfaces (MonoClass *klass, int *num, int *is_enumerator)
3087 MonoClass *eclass = klass->element_class;
3088 static MonoClass* generic_icollection_class = NULL;
3089 static MonoClass* generic_ienumerable_class = NULL;
3090 static MonoClass* generic_ienumerator_class = NULL;
3091 static MonoClass* generic_ireadonlylist_class = NULL;
3092 static MonoClass* generic_ireadonlycollection_class = NULL;
3093 MonoClass *valuetype_types[2] = { NULL, NULL };
3094 MonoClass **interfaces = NULL;
3095 int i, nifaces, interface_count, real_count, original_rank;
3097 gboolean internal_enumerator;
3098 gboolean eclass_is_valuetype;
3100 if (!mono_defaults.generic_ilist_class) {
3104 internal_enumerator = FALSE;
3105 eclass_is_valuetype = FALSE;
3106 original_rank = eclass->rank;
3107 if (klass->byval_arg.type != MONO_TYPE_SZARRAY) {
3108 if (klass->generic_class && klass->nested_in == mono_defaults.array_class && strcmp (klass->name, "InternalEnumerator`1") == 0) {
3110 * For a Enumerator<T[]> we need to get the list of interfaces for T.
3112 eclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
3113 original_rank = eclass->rank;
3115 eclass = eclass->element_class;
3116 internal_enumerator = TRUE;
3117 *is_enumerator = TRUE;
3125 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
3126 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
3128 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
3130 if (!generic_icollection_class) {
3131 generic_icollection_class = mono_class_load_from_name (mono_defaults.corlib,
3132 "System.Collections.Generic", "ICollection`1");
3133 generic_ienumerable_class = mono_class_load_from_name (mono_defaults.corlib,
3134 "System.Collections.Generic", "IEnumerable`1");
3135 generic_ienumerator_class = mono_class_load_from_name (mono_defaults.corlib,
3136 "System.Collections.Generic", "IEnumerator`1");
3137 generic_ireadonlylist_class = mono_class_load_from_name (mono_defaults.corlib,
3138 "System.Collections.Generic", "IReadOnlyList`1");
3139 generic_ireadonlycollection_class = mono_class_load_from_name (mono_defaults.corlib,
3140 "System.Collections.Generic", "IReadOnlyCollection`1");
3143 mono_class_init (eclass);
3146 * Arrays in 2.0 need to implement a number of generic interfaces
3147 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
3148 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
3149 * We collect the types needed to build the
3150 * instantiations in interfaces at intervals of 3/5, because 3/5 are
3151 * the generic interfaces needed to implement.
3153 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
3154 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
3156 if (eclass->valuetype) {
3157 nifaces = generic_ireadonlylist_class ? 5 : 3;
3158 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
3160 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
3161 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
3162 if (internal_enumerator) {
3164 if (valuetype_types [1])
3168 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3169 interfaces [0] = valuetype_types [0];
3170 if (valuetype_types [1])
3171 interfaces [nifaces] = valuetype_types [1];
3173 eclass_is_valuetype = TRUE;
3176 int idepth = eclass->idepth;
3177 if (!internal_enumerator)
3179 nifaces = generic_ireadonlylist_class ? 2 : 3;
3181 // FIXME: This doesn't seem to work/required for generic params
3182 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
3183 mono_class_setup_interface_offsets (eclass);
3185 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
3186 /* we add object for interfaces and the supertypes for the other
3187 * types. The last of the supertypes is the element class itself which we
3188 * already created the explicit interfaces for (so we include it for IEnumerator
3189 * and exclude it for arrays).
3191 if (MONO_CLASS_IS_INTERFACE (eclass))
3194 interface_count += idepth;
3195 if (eclass->rank && eclass->element_class->valuetype) {
3196 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3197 if (valuetype_types [1])
3200 /* IList, ICollection, IEnumerable, IReadOnlyList */
3201 interface_count *= nifaces;
3202 real_count = interface_count;
3203 if (internal_enumerator) {
3204 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3205 if (valuetype_types [1])
3208 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3209 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3210 interfaces [0] = mono_defaults.object_class;
3214 for (i = 0; i < idepth; i++) {
3215 mono_class_init (eclass->supertypes [i]);
3216 interfaces [j] = eclass->supertypes [i];
3220 if (all_interfaces) {
3221 for (i = 0; i < eclass->interface_offsets_count; i++) {
3222 interfaces [j] = eclass->interfaces_packed [i];
3226 for (i = 0; i < eclass->interface_count; i++) {
3227 interfaces [j] = eclass->interfaces [i];
3231 if (valuetype_types [1]) {
3232 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3237 /* instantiate the generic interfaces */
3238 for (i = 0; i < interface_count; i += nifaces) {
3239 MonoClass *iface = interfaces [i];
3241 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3242 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3244 if (eclass->valuetype) {
3245 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3246 if (generic_ireadonlylist_class) {
3247 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3248 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3251 if (!generic_ireadonlylist_class)
3252 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3255 if (internal_enumerator) {
3257 /* instantiate IEnumerator<iface> */
3258 for (i = 0; i < interface_count; i++) {
3259 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3261 j = interface_count;
3262 if (!eclass_is_valuetype) {
3263 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3264 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3267 for (i = 0; i < eclass->idepth; i++) {
3268 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3272 for (i = 0; i < eclass->interface_offsets_count; i++) {
3273 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3277 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3279 if (valuetype_types [1])
3280 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3284 char *type_name = mono_type_get_name_full (&klass->byval_arg, 0);
3285 for (i = 0; i < real_count; ++i) {
3286 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3287 g_print ("%s implements %s\n", type_name, name);
3298 find_array_interface (MonoClass *klass, const char *name)
3301 for (i = 0; i < klass->interface_count; ++i) {
3302 if (strcmp (klass->interfaces [i]->name, name) == 0)
3309 * Return the number of virtual methods.
3310 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3311 * Return -1 on failure.
3312 * FIXME It would be nice if this information could be cached somewhere.
3315 count_virtual_methods (MonoClass *klass)
3319 klass = mono_class_get_generic_type_definition (klass); /*We can find this information by looking at the GTD*/
3321 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
3322 mono_class_setup_methods (klass);
3323 if (mono_class_has_failure (klass))
3326 for (i = 0; i < klass->method.count; ++i) {
3327 flags = klass->methods [i]->flags;
3328 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3332 for (i = 0; i < klass->method.count; ++i) {
3333 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
3335 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3343 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3351 m = (l + num_ifaces) / 2;
3352 if (interfaces_full [m] == ic)
3354 if (l == num_ifaces)
3356 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3365 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3367 int i = find_interface (num_ifaces, interfaces_full, ic);
3369 return interface_offsets_full [i];
3374 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3376 int i = find_interface (num_ifaces, interfaces_full, ic);
3380 interface_offsets_full [i] = offset;
3383 for (i = 0; i < num_ifaces; ++i) {
3384 if (interfaces_full [i]) {
3386 if (interfaces_full [i]->interface_id < ic->interface_id)
3389 while (end < num_ifaces && interfaces_full [end]) end++;
3390 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3391 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3393 interfaces_full [i] = ic;
3394 interface_offsets_full [i] = offset;
3400 #ifdef COMPRESSED_INTERFACE_BITMAP
3403 * Compressed interface bitmap design.
3405 * Interface bitmaps take a large amount of memory, because their size is
3406 * linear with the maximum interface id assigned in the process (each interface
3407 * is assigned a unique id as it is loaded). The number of interface classes
3408 * is high because of the many implicit interfaces implemented by arrays (we'll
3409 * need to lazy-load them in the future).
3410 * Most classes implement a very small number of interfaces, so the bitmap is
3411 * sparse. This bitmap needs to be checked by interface casts, so access to the
3412 * needed bit must be fast and doable with few jit instructions.
3414 * The current compression format is as follows:
3415 * *) it is a sequence of one or more two-byte elements
3416 * *) the first byte in the element is the count of empty bitmap bytes
3417 * at the current bitmap position
3418 * *) the second byte in the element is an actual bitmap byte at the current
3421 * As an example, the following compressed bitmap bytes:
3422 * 0x07 0x01 0x00 0x7
3423 * correspond to the following bitmap:
3424 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3426 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3427 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3428 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3432 * mono_compress_bitmap:
3433 * @dest: destination buffer
3434 * @bitmap: bitmap buffer
3435 * @size: size of @bitmap in bytes
3437 * This is a mono internal function.
3438 * The @bitmap data is compressed into a format that is small but
3439 * still searchable in few instructions by the JIT and runtime.
3440 * The compressed data is stored in the buffer pointed to by the
3441 * @dest array. Passing a #NULL value for @dest allows to just compute
3442 * the size of the buffer.
3443 * This compression algorithm assumes the bits set in the bitmap are
3444 * few and far between, like in interface bitmaps.
3445 * Returns: The size of the compressed bitmap in bytes.
3448 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3452 const uint8_t *end = bitmap + size;
3453 while (bitmap < end) {
3454 if (*bitmap || numz == 255) {
3478 * mono_class_interface_match:
3479 * @bitmap: a compressed bitmap buffer
3480 * @id: the index to check in the bitmap
3482 * This is a mono internal function.
3483 * Checks if a bit is set in a compressed interface bitmap. @id must
3484 * be already checked for being smaller than the maximum id encoded in the
3487 * Returns: A non-zero value if bit @id is set in the bitmap @bitmap,
3491 mono_class_interface_match (const uint8_t *bitmap, int id)
3494 id -= bitmap [0] * 8;
3498 return bitmap [1] & (1 << id);
3507 * LOCKING: this is supposed to be called with the loader lock held.
3508 * Return -1 on failure and set klass->has_failure and store a MonoErrorBoxed with the details.
3511 setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite)
3515 int i, j, max_iid, num_ifaces;
3516 MonoClass **interfaces_full = NULL;
3517 int *interface_offsets_full = NULL;
3519 GPtrArray **ifaces_array = NULL;
3520 int interface_offsets_count;
3521 MonoClass **array_interfaces = NULL;
3522 int num_array_interfaces;
3523 int is_enumerator = FALSE;
3525 mono_class_setup_supertypes (klass);
3527 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3528 * implicit interfaces have the property that they are assigned the same slot in the
3529 * vtables for compatible interfaces
3531 array_interfaces = get_implicit_generic_array_interfaces (klass, &num_array_interfaces, &is_enumerator);
3533 /* compute maximum number of slots and maximum interface id */
3535 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3536 ifaces_array = g_new0 (GPtrArray *, klass->idepth);
3537 for (j = 0; j < klass->idepth; j++) {
3538 k = klass->supertypes [j];
3539 num_ifaces += k->interface_count;
3540 for (i = 0; i < k->interface_count; i++) {
3541 ic = k->interfaces [i];
3544 mono_class_init (ic);
3546 if (max_iid < ic->interface_id)
3547 max_iid = ic->interface_id;
3549 ifaces = mono_class_get_implemented_interfaces (k, &error);
3550 if (!mono_error_ok (&error)) {
3551 char *name = mono_type_get_full_name (k);
3552 mono_class_set_type_load_failure (klass, "Error getting the interfaces of %s due to %s", name, mono_error_get_message (&error));
3554 mono_error_cleanup (&error);
3559 num_ifaces += ifaces->len;
3560 for (i = 0; i < ifaces->len; ++i) {
3561 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3562 if (max_iid < ic->interface_id)
3563 max_iid = ic->interface_id;
3565 ifaces_array [j] = ifaces;
3569 for (i = 0; i < num_array_interfaces; ++i) {
3570 ic = array_interfaces [i];
3571 mono_class_init (ic);
3572 if (max_iid < ic->interface_id)
3573 max_iid = ic->interface_id;
3576 if (MONO_CLASS_IS_INTERFACE (klass)) {
3578 if (max_iid < klass->interface_id)
3579 max_iid = klass->interface_id;
3581 klass->max_interface_id = max_iid;
3582 /* compute vtable offset for interfaces */
3583 interfaces_full = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3584 interface_offsets_full = (int *)g_malloc (sizeof (int) * num_ifaces);
3586 for (i = 0; i < num_ifaces; i++) {
3587 interface_offsets_full [i] = -1;
3590 /* skip the current class */
3591 for (j = 0; j < klass->idepth - 1; j++) {
3592 k = klass->supertypes [j];
3593 ifaces = ifaces_array [j];
3596 for (i = 0; i < ifaces->len; ++i) {
3598 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3600 /*Force the sharing of interface offsets between parent and subtypes.*/
3601 io = mono_class_interface_offset (k, ic);
3603 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3608 g_assert (klass == klass->supertypes [klass->idepth - 1]);
3609 ifaces = ifaces_array [klass->idepth - 1];
3611 for (i = 0; i < ifaces->len; ++i) {
3613 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3614 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3616 count = count_virtual_methods (ic);
3618 char *name = mono_type_get_full_name (ic);
3619 mono_class_set_type_load_failure (klass, "Error calculating interface offset of %s", name);
3628 if (MONO_CLASS_IS_INTERFACE (klass))
3629 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, klass, cur_slot, TRUE);
3631 if (num_array_interfaces) {
3632 if (is_enumerator) {
3633 int ienumerator_idx = find_array_interface (klass, "IEnumerator`1");
3634 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ienumerator_idx]);
3635 g_assert (ienumerator_offset >= 0);
3636 for (i = 0; i < num_array_interfaces; ++i) {
3637 ic = array_interfaces [i];
3638 if (strcmp (ic->name, "IEnumerator`1") == 0)
3639 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3641 g_assert_not_reached ();
3642 /*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);*/
3645 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3646 int ilist_iface_idx = find_array_interface (klass, "IList`1");
3647 MonoClass* ilist_class = klass->interfaces [ilist_iface_idx];
3648 int ireadonlylist_iface_idx = find_array_interface (klass, "IReadOnlyList`1");
3649 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? klass->interfaces [ireadonlylist_iface_idx] : NULL;
3650 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3651 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3652 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3653 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ilist_iface_idx]);
3654 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3655 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3656 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ireadonlylist_iface_idx]) : -1;
3657 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3658 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3659 for (i = 0; i < num_array_interfaces; ++i) {
3661 ic = array_interfaces [i];
3662 if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
3663 offset = ilist_offset;
3664 else if (strcmp (ic->name, "ICollection`1") == 0)
3665 offset = icollection_offset;
3666 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3667 offset = ienumerable_offset;
3668 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3669 offset = ireadonlylist_offset;
3670 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3671 offset = ireadonlycollection_offset;
3673 g_assert_not_reached ();
3674 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3675 /*g_print ("type %s has %s offset at %d (%s)\n", klass->name, ic->name, offset, klass->interfaces [0]->name);*/
3680 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3681 if (interface_offsets_full [i] != -1) {
3682 interface_offsets_count ++;
3687 * We might get called multiple times:
3688 * - mono_class_init ()
3689 * - mono_class_setup_vtable ().
3690 * - mono_class_setup_interface_offsets ().
3691 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3692 * means we have to overwrite those when called from other places (#4440).
3694 if (klass->interfaces_packed) {
3696 g_assert (klass->interface_offsets_count == interface_offsets_count);
3700 klass->interface_offsets_count = interface_offsets_count;
3701 klass->interfaces_packed = (MonoClass **)mono_class_alloc (klass, sizeof (MonoClass*) * interface_offsets_count);
3702 klass->interface_offsets_packed = (guint16 *)mono_class_alloc (klass, sizeof (guint16) * interface_offsets_count);
3703 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3704 #ifdef COMPRESSED_INTERFACE_BITMAP
3705 bitmap = g_malloc0 (bsize);
3707 bitmap = (uint8_t *)mono_class_alloc0 (klass, bsize);
3709 for (i = 0; i < interface_offsets_count; i++) {
3710 int id = interfaces_full [i]->interface_id;
3711 bitmap [id >> 3] |= (1 << (id & 7));
3712 klass->interfaces_packed [i] = interfaces_full [i];
3713 klass->interface_offsets_packed [i] = interface_offsets_full [i];
3714 /*if (num_array_interfaces)
3715 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]);*/
3717 #ifdef COMPRESSED_INTERFACE_BITMAP
3718 i = mono_compress_bitmap (NULL, bitmap, bsize);
3719 klass->interface_bitmap = mono_class_alloc0 (klass, i);
3720 mono_compress_bitmap (klass->interface_bitmap, bitmap, bsize);
3723 klass->interface_bitmap = bitmap;
3728 g_free (interfaces_full);
3729 g_free (interface_offsets_full);
3730 g_free (array_interfaces);
3731 for (i = 0; i < klass->idepth; i++) {
3732 ifaces = ifaces_array [i];
3734 g_ptr_array_free (ifaces, TRUE);
3736 g_free (ifaces_array);
3738 //printf ("JUST DONE: ");
3739 //print_implemented_interfaces (klass);
3745 * Setup interface offsets for interfaces.
3747 * - klass->max_interface_id
3748 * - klass->interface_offsets_count
3749 * - klass->interfaces_packed
3750 * - klass->interface_offsets_packed
3751 * - klass->interface_bitmap
3753 * This function can fail @class.
3756 mono_class_setup_interface_offsets (MonoClass *klass)
3758 mono_loader_lock ();
3760 setup_interface_offsets (klass, 0, FALSE);
3762 mono_loader_unlock ();
3765 /*Checks if @klass has @parent as one of it's parents type gtd
3769 * Bar<T> : Foo<Bar<Bar<T>>>
3773 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3775 klass = mono_class_get_generic_type_definition (klass);
3776 parent = mono_class_get_generic_type_definition (parent);
3777 mono_class_setup_supertypes (klass);
3778 mono_class_setup_supertypes (parent);
3780 return klass->idepth >= parent->idepth &&
3781 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3785 mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup)
3787 MonoGenericInst *ginst;
3789 if (!klass->generic_class) {
3790 mono_class_setup_vtable_full (klass, in_setup);
3791 return !mono_class_has_failure (klass);
3794 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup);
3795 if (mono_class_set_type_load_failure_causedby_class (klass, klass->generic_class->container_class, "Failed to load generic definition vtable"))
3798 ginst = klass->generic_class->context.class_inst;
3799 for (i = 0; i < ginst->type_argc; ++i) {
3801 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3803 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3804 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3805 if (mono_class_has_gtd_parent (klass, arg) || mono_class_has_gtd_parent (arg, klass))
3807 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3808 mono_class_set_type_load_failure (klass, "Failed to load generic parameter %d", i);
3816 * mono_class_setup_vtable:
3818 * Creates the generic vtable of CLASS.
3819 * Initializes the following fields in MonoClass:
3822 * Plus all the fields initialized by setup_interface_offsets ().
3823 * If there is an error during vtable construction, klass->has_failure
3824 * is set and details are stored in a MonoErrorBoxed.
3826 * LOCKING: Acquires the loader lock.
3829 mono_class_setup_vtable (MonoClass *klass)
3831 mono_class_setup_vtable_full (klass, NULL);
3835 mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
3838 MonoMethod **overrides;
3839 MonoGenericContext *context;
3847 if (MONO_CLASS_IS_INTERFACE (klass)) {
3848 /* This sets method->slot for all methods if this is an interface */
3849 mono_class_setup_methods (klass);
3853 if (mono_class_has_failure (klass))
3856 if (g_list_find (in_setup, klass))
3859 mono_loader_lock ();
3861 if (klass->vtable) {
3862 mono_loader_unlock ();
3866 mono_stats.generic_vtable_count ++;
3867 in_setup = g_list_prepend (in_setup, klass);
3869 if (klass->generic_class) {
3870 if (!mono_class_check_vtable_constraints (klass, in_setup)) {
3871 mono_loader_unlock ();
3872 g_list_remove (in_setup, klass);
3876 context = mono_class_get_context (klass);
3877 type_token = klass->generic_class->container_class->type_token;
3879 context = (MonoGenericContext *) klass->generic_container;
3880 type_token = klass->type_token;
3883 if (image_is_dynamic (klass->image)) {
3884 /* Generic instances can have zero method overrides without causing any harm.
3885 * This is true since we don't do layout all over again for them, we simply inflate
3886 * the layout of the parent.
3888 mono_reflection_get_dynamic_overrides (klass, &overrides, &onum, &error);
3889 if (!is_ok (&error)) {
3890 mono_loader_unlock ();
3891 g_list_remove (in_setup, klass);
3892 mono_class_set_type_load_failure (klass, "Could not load list of method overrides due to %s", mono_error_get_message (&error));
3893 mono_error_cleanup (&error);
3897 /* The following call fails if there are missing methods in the type */
3898 /* FIXME it's probably a good idea to avoid this for generic instances. */
3899 ok = mono_class_get_overrides_full (klass->image, type_token, &overrides, &onum, context);
3903 mono_class_setup_vtable_general (klass, overrides, onum, in_setup);
3905 mono_class_set_type_load_failure (klass, "Could not load list of method overrides");
3909 mono_loader_unlock ();
3910 g_list_remove (in_setup, klass);
3915 #define DEBUG_INTERFACE_VTABLE_CODE 0
3916 #define TRACE_INTERFACE_VTABLE_CODE 0
3917 #define VERIFY_INTERFACE_VTABLE_CODE 0
3918 #define VTABLE_SELECTOR (1)
3920 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3921 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3922 if (!(VTABLE_SELECTOR)) break; \
3926 #define DEBUG_INTERFACE_VTABLE(stmt)
3929 #if TRACE_INTERFACE_VTABLE_CODE
3930 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3931 if (!(VTABLE_SELECTOR)) break; \
3935 #define TRACE_INTERFACE_VTABLE(stmt)
3938 #if VERIFY_INTERFACE_VTABLE_CODE
3939 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3940 if (!(VTABLE_SELECTOR)) break; \
3944 #define VERIFY_INTERFACE_VTABLE(stmt)
3948 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3950 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3954 GString *res = g_string_new ("");
3956 g_string_append_c (res, '(');
3957 for (i = 0; i < sig->param_count; ++i) {
3959 g_string_append_c (res, ',');
3960 mono_type_get_desc (res, sig->params [i], include_namespace);
3962 g_string_append (res, ")=>");
3963 if (sig->ret != NULL) {
3964 mono_type_get_desc (res, sig->ret, include_namespace);
3966 g_string_append (res, "NULL");
3969 g_string_free (res, FALSE);
3973 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3974 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3975 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3976 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3984 is_wcf_hack_disabled (void)
3986 static gboolean disabled;
3987 static gboolean inited = FALSE;
3989 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3996 check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
3998 MonoMethodSignature *cmsig, *imsig;
3999 if (strcmp (im->name, cm->name) == 0) {
4000 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
4001 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
4004 if (! slot_is_empty) {
4005 if (require_newslot) {
4006 if (! interface_is_explicitly_implemented_by_class) {
4007 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
4010 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4011 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
4015 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
4018 cmsig = mono_method_signature (cm);
4019 imsig = mono_method_signature (im);
4020 if (!cmsig || !imsig) {
4021 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
4025 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4026 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
4027 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4028 TRACE_INTERFACE_VTABLE (printf ("]"));
4031 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
4032 if (mono_security_core_clr_enabled ())
4033 mono_security_core_clr_check_override (klass, cm, im);
4035 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
4036 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4037 char *body_name = mono_method_full_name (cm, TRUE);
4038 char *decl_name = mono_method_full_name (im, TRUE);
4039 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4047 MonoClass *ic = im->klass;
4048 const char *ic_name_space = ic->name_space;
4049 const char *ic_name = ic->name;
4052 if (! require_newslot) {
4053 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
4056 if (cm->klass->rank == 0) {
4057 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
4060 cmsig = mono_method_signature (cm);
4061 imsig = mono_method_signature (im);
4062 if (!cmsig || !imsig) {
4063 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
4067 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4068 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
4069 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4070 TRACE_INTERFACE_VTABLE (printf ("]"));
4073 if (mono_class_get_image (ic) != mono_defaults.corlib) {
4074 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
4077 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
4078 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
4081 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))) {
4082 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
4086 subname = strstr (cm->name, ic_name_space);
4087 if (subname != cm->name) {
4088 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
4091 subname += strlen (ic_name_space);
4092 if (subname [0] != '.') {
4093 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
4097 if (strstr (subname, ic_name) != subname) {
4098 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
4101 subname += strlen (ic_name);
4102 if (subname [0] != '.') {
4103 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
4107 if (strcmp (subname, im->name) != 0) {
4108 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
4112 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
4113 if (mono_security_core_clr_enabled ())
4114 mono_security_core_clr_check_override (klass, cm, im);
4116 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
4117 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4118 char *body_name = mono_method_full_name (cm, TRUE);
4119 char *decl_name = mono_method_full_name (im, TRUE);
4120 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4130 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
4132 foreach_override (gpointer key, gpointer value, gpointer user_data) {
4133 MonoMethod *method = key;
4134 MonoMethod *override = value;
4135 MonoClass *method_class = mono_method_get_class (method);
4136 MonoClass *override_class = mono_method_get_class (override);
4138 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
4139 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
4140 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
4143 print_overrides (GHashTable *override_map, const char *message) {
4145 printf ("Override map \"%s\" START:\n", message);
4146 g_hash_table_foreach (override_map, foreach_override, NULL);
4147 printf ("Override map \"%s\" END.\n", message);
4149 printf ("Override map \"%s\" EMPTY.\n", message);
4153 print_vtable_full (MonoClass *klass, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
4154 char *full_name = mono_type_full_name (&klass->byval_arg);
4158 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
4160 if (print_interfaces) {
4161 print_implemented_interfaces (klass);
4162 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
4165 if (klass->parent) {
4166 parent_size = klass->parent->vtable_size;
4170 for (i = 0; i < size; ++i) {
4171 MonoMethod *cm = vtable [i];
4172 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
4173 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
4175 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
4183 #if VERIFY_INTERFACE_VTABLE_CODE
4185 mono_method_try_get_vtable_index (MonoMethod *method)
4187 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4188 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4189 if (imethod->declaring->is_generic)
4190 return imethod->declaring->slot;
4192 return method->slot;
4196 mono_class_verify_vtable (MonoClass *klass)
4199 char *full_name = mono_type_full_name (&klass->byval_arg);
4201 printf ("*** Verifying VTable of class '%s' \n", full_name);
4205 if (!klass->methods)
4208 for (i = 0; i < klass->method.count; ++i) {
4209 MonoMethod *cm = klass->methods [i];
4212 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4216 full_name = mono_method_full_name (cm, TRUE);
4218 slot = mono_method_try_get_vtable_index (cm);
4220 if (slot >= klass->vtable_size) {
4221 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, klass->vtable_size);
4225 if (slot >= 0 && klass->vtable [slot] != cm && (klass->vtable [slot])) {
4226 char *other_name = klass->vtable [slot] ? mono_method_full_name (klass->vtable [slot], TRUE) : g_strdup ("[null value]");
4227 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4228 g_free (other_name);
4231 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4238 print_unimplemented_interface_method_info (MonoClass *klass, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4240 char *method_signature;
4243 for (index = 0; index < onum; ++index) {
4244 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4245 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4247 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4248 type_name = mono_type_full_name (&klass->byval_arg);
4249 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4250 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4251 g_free (method_signature);
4253 mono_class_setup_methods (klass);
4254 if (mono_class_has_failure (klass)) {
4255 char *name = mono_type_get_full_name (klass);
4256 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4260 for (index = 0; index < klass->method.count; ++index) {
4261 MonoMethod *cm = klass->methods [index];
4262 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4264 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4265 g_free (method_signature);
4270 mono_method_get_method_definition (MonoMethod *method)
4272 while (method->is_inflated)
4273 method = ((MonoMethodInflated*)method)->declaring;
4278 verify_class_overrides (MonoClass *klass, MonoMethod **overrides, int onum)
4282 for (i = 0; i < onum; ++i) {
4283 MonoMethod *decl = overrides [i * 2];
4284 MonoMethod *body = overrides [i * 2 + 1];
4286 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (klass)) {
4287 mono_class_set_type_load_failure (klass, "Method belongs to a different class than the declared one");
4291 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4292 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4293 mono_class_set_type_load_failure (klass, "Method must not be static to override a base type");
4295 mono_class_set_type_load_failure (klass, "Method must be virtual to override a base type");
4299 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4300 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4301 mono_class_set_type_load_failure (klass, "Cannot override a static method in a base type");
4303 mono_class_set_type_load_failure (klass, "Cannot override a non virtual method in a base type");
4307 if (!mono_class_is_assignable_from_slow (decl->klass, klass)) {
4308 mono_class_set_type_load_failure (klass, "Method overrides a class or interface that is not extended or implemented by this type");
4312 body = mono_method_get_method_definition (body);
4313 decl = mono_method_get_method_definition (decl);
4315 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4316 char *body_name = mono_method_full_name (body, TRUE);
4317 char *decl_name = mono_method_full_name (decl, TRUE);
4318 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4328 mono_class_need_stelemref_method (MonoClass *klass)
4330 return klass->rank == 1 && MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg);
4334 * LOCKING: this is supposed to be called with the loader lock held.
4337 mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int onum, GList *in_setup)
4341 MonoMethod **vtable;
4342 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4343 GPtrArray *ifaces = NULL;
4344 GHashTable *override_map = NULL;
4346 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4347 int first_non_interface_slot;
4349 GSList *virt_methods = NULL, *l;
4350 int stelemref_slot = 0;
4355 if (overrides && !verify_class_overrides (klass, overrides, onum))
4358 ifaces = mono_class_get_implemented_interfaces (klass, &error);
4359 if (!mono_error_ok (&error)) {
4360 char *name = mono_type_get_full_name (klass);
4361 mono_class_set_type_load_failure (klass, "Could not resolve %s interfaces due to %s", name, mono_error_get_message (&error));
4363 mono_error_cleanup (&error);
4365 } else if (ifaces) {
4366 for (i = 0; i < ifaces->len; i++) {
4367 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
4368 max_vtsize += ic->method.count;
4370 g_ptr_array_free (ifaces, TRUE);
4374 if (klass->parent) {
4375 mono_class_init (klass->parent);
4376 mono_class_setup_vtable_full (klass->parent, in_setup);
4378 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class failed to load"))
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_set_type_load_failure_causedby_class (klass, gklass, "Could not load generic definition"))
4416 tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * gklass->vtable_size);
4417 klass->vtable_size = gklass->vtable_size;
4418 for (i = 0; i < gklass->vtable_size; ++i)
4419 if (gklass->vtable [i]) {
4420 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], klass, mono_class_get_context (klass), &error);
4421 if (!mono_error_ok (&error)) {
4422 mono_class_set_type_load_failure (klass, "Could not inflate method due to %s", mono_error_get_message (&error));
4423 mono_error_cleanup (&error);
4427 tmp [i]->slot = gklass->vtable [i]->slot;
4429 mono_memory_barrier ();
4430 klass->vtable = tmp;
4432 /* Have to set method->slot for abstract virtual methods */
4433 if (klass->methods && gklass->methods) {
4434 for (i = 0; i < klass->method.count; ++i)
4435 if (klass->methods [i]->slot == -1)
4436 klass->methods [i]->slot = gklass->methods [i]->slot;
4442 if (klass->parent && klass->parent->vtable_size) {
4443 MonoClass *parent = klass->parent;
4446 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4448 // Also inherit parent interface vtables, just as a starting point.
4449 // This is needed otherwise bug-77127.exe fails when the property methods
4450 // have different names in the iterface and the class, because for child
4451 // classes the ".override" information is not used anymore.
4452 for (i = 0; i < parent->interface_offsets_count; i++) {
4453 MonoClass *parent_interface = parent->interfaces_packed [i];
4454 int interface_offset = mono_class_interface_offset (klass, parent_interface);
4455 /*FIXME this is now dead code as this condition will never hold true.
4456 Since interface offsets are inherited then the offset of an interface implemented
4457 by a parent will never be the out of it's vtable boundary.
4459 if (interface_offset >= parent->vtable_size) {
4460 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4463 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4464 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4465 for (j = 0; j < parent_interface->method.count && !mono_class_has_failure (klass); j++) {
4466 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4467 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4468 parent_interface_offset + j, parent_interface_offset, j,
4469 interface_offset + j, interface_offset, j));
4476 /*Array have a slot for stelemref*/
4477 if (mono_class_need_stelemref_method (klass)) {
4478 MonoMethod *method = mono_marshal_get_virtual_stelemref (klass);
4480 method->slot = stelemref_slot;
4482 g_assert (method->slot == stelemref_slot);
4484 vtable [stelemref_slot] = method;
4487 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4488 /* override interface methods */
4489 for (i = 0; i < onum; i++) {
4490 MonoMethod *decl = overrides [i*2];
4491 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4493 dslot = mono_method_get_vtable_slot (decl);
4495 mono_class_set_type_load_failure (klass, "");
4499 dslot += mono_class_interface_offset (klass, decl->klass);
4500 vtable [dslot] = overrides [i*2 + 1];
4501 vtable [dslot]->slot = dslot;
4503 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4505 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4507 if (mono_security_core_clr_enabled ())
4508 mono_security_core_clr_check_override (klass, vtable [dslot], decl);
4511 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4512 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4515 * Create a list of virtual methods to avoid calling
4516 * mono_class_get_virtual_methods () which is slow because of the metadata
4520 gpointer iter = NULL;
4523 virt_methods = NULL;
4524 while ((cm = mono_class_get_virtual_methods (klass, &iter))) {
4525 virt_methods = g_slist_prepend (virt_methods, cm);
4527 if (mono_class_has_failure (klass))
4531 // Loop on all implemented interfaces...
4532 for (i = 0; i < klass->interface_offsets_count; i++) {
4533 MonoClass *parent = klass->parent;
4535 gboolean interface_is_explicitly_implemented_by_class;
4538 ic = klass->interfaces_packed [i];
4539 ic_offset = mono_class_interface_offset (klass, ic);
4541 mono_class_setup_methods (ic);
4542 if (mono_class_has_failure (ic))
4545 // Check if this interface is explicitly implemented (instead of just inherited)
4546 if (parent != NULL) {
4547 int implemented_interfaces_index;
4548 interface_is_explicitly_implemented_by_class = FALSE;
4549 for (implemented_interfaces_index = 0; implemented_interfaces_index < klass->interface_count; implemented_interfaces_index++) {
4550 if (ic == klass->interfaces [implemented_interfaces_index]) {
4551 interface_is_explicitly_implemented_by_class = TRUE;
4556 interface_is_explicitly_implemented_by_class = TRUE;
4559 // Loop on all interface methods...
4560 for (im_index = 0; im_index < ic->method.count; im_index++) {
4561 MonoMethod *im = ic->methods [im_index];
4562 int im_slot = ic_offset + im->slot;
4563 MonoMethod *override_im = (override_map != NULL) ? (MonoMethod *)g_hash_table_lookup (override_map, im) : NULL;
4565 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4568 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4570 // If there is an explicit implementation, just use it right away,
4571 // otherwise look for a matching method
4572 if (override_im == NULL) {
4576 // First look for a suitable method among the class methods
4577 for (l = virt_methods; l; l = l->next) {
4578 cm = (MonoMethod *)l->data;
4579 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)));
4580 if (check_interface_method_override (klass, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
4581 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4582 vtable [im_slot] = cm;
4583 /* Why do we need this? */
4588 TRACE_INTERFACE_VTABLE (printf ("\n"));
4589 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4593 // If the slot is still empty, look in all the inherited virtual methods...
4594 if ((vtable [im_slot] == NULL) && klass->parent != NULL) {
4595 MonoClass *parent = klass->parent;
4596 // Reverse order, so that last added methods are preferred
4597 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4598 MonoMethod *cm = parent->vtable [cm_index];
4600 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));
4601 if ((cm != NULL) && check_interface_method_override (klass, im, cm, FALSE, FALSE, TRUE)) {
4602 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4603 vtable [im_slot] = cm;
4604 /* Why do we need this? */
4610 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4612 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4616 g_assert (vtable [im_slot] == override_im);
4621 // If the class is not abstract, check that all its interface slots are full.
4622 // The check is done here and not directly at the end of the loop above because
4623 // it can happen (for injected generic array interfaces) that the same slot is
4624 // processed multiple times (those interfaces have overlapping slots), and it
4625 // will not always be the first pass the one that fills the slot.
4626 if (! (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4627 for (i = 0; i < klass->interface_offsets_count; i++) {
4631 ic = klass->interfaces_packed [i];
4632 ic_offset = mono_class_interface_offset (klass, ic);
4634 for (im_index = 0; im_index < ic->method.count; im_index++) {
4635 MonoMethod *im = ic->methods [im_index];
4636 int im_slot = ic_offset + im->slot;
4638 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4641 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4642 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4643 if (vtable [im_slot] == NULL) {
4644 print_unimplemented_interface_method_info (klass, ic, im, im_slot, overrides, onum);
4651 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4652 for (l = virt_methods; l; l = l->next) {
4653 cm = (MonoMethod *)l->data;
4655 * If the method is REUSE_SLOT, we must check in the
4656 * base class for a method to override.
4658 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4660 for (k = klass->parent; k ; k = k->parent) {
4665 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4666 MonoMethodSignature *cmsig, *m1sig;
4668 cmsig = mono_method_signature (cm);
4669 m1sig = mono_method_signature (m1);
4671 if (!cmsig || !m1sig) {
4672 /* FIXME proper error message */
4673 mono_class_set_type_load_failure (klass, "");
4677 if (!strcmp(cm->name, m1->name) &&
4678 mono_metadata_signature_equal (cmsig, m1sig)) {
4680 if (mono_security_core_clr_enabled ())
4681 mono_security_core_clr_check_override (klass, cm, m1);
4683 slot = mono_method_get_vtable_slot (m1);
4687 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4688 char *body_name = mono_method_full_name (cm, TRUE);
4689 char *decl_name = mono_method_full_name (m1, TRUE);
4690 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4696 g_assert (cm->slot < max_vtsize);
4698 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4699 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4700 mono_method_full_name (m1, 1), m1,
4701 mono_method_full_name (cm, 1), cm));
4702 g_hash_table_insert (override_map, m1, cm);
4706 if (mono_class_has_failure (k))
4716 /*Non final newslot methods must be given a non-interface vtable slot*/
4717 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4721 cm->slot = cur_slot++;
4723 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4724 vtable [cm->slot] = cm;
4727 /* override non interface methods */
4728 for (i = 0; i < onum; i++) {
4729 MonoMethod *decl = overrides [i*2];
4730 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4731 g_assert (decl->slot != -1);
4732 vtable [decl->slot] = overrides [i*2 + 1];
4733 overrides [i * 2 + 1]->slot = decl->slot;
4735 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4736 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4737 mono_method_full_name (decl, 1), decl,
4738 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4739 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4741 if (mono_security_core_clr_enabled ())
4742 mono_security_core_clr_check_override (klass, vtable [decl->slot], decl);
4747 * If a method occupies more than one place in the vtable, and it is
4748 * overriden, then change the other occurances too.
4753 for (i = 0; i < max_vtsize; ++i)
4755 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4757 cm = (MonoMethod *)g_hash_table_lookup (override_map, vtable [i]);
4762 g_hash_table_destroy (override_map);
4763 override_map = NULL;
4766 g_slist_free (virt_methods);
4767 virt_methods = NULL;
4769 /* Ensure that all vtable slots are filled with concrete instance methods */
4770 if (!(klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4771 for (i = 0; i < cur_slot; ++i) {
4772 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4773 char *type_name = mono_type_get_full_name (klass);
4774 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4775 mono_class_set_type_load_failure (klass, "Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name);
4777 g_free (method_name);
4783 if (klass->generic_class) {
4784 MonoClass *gklass = klass->generic_class->container_class;
4786 mono_class_init (gklass);
4788 klass->vtable_size = MAX (gklass->vtable_size, cur_slot);
4790 /* Check that the vtable_size value computed in mono_class_init () is correct */
4791 if (klass->vtable_size)
4792 g_assert (cur_slot == klass->vtable_size);
4793 klass->vtable_size = cur_slot;
4796 /* Try to share the vtable with our parent. */
4797 if (klass->parent && (klass->parent->vtable_size == klass->vtable_size) && (memcmp (klass->parent->vtable, vtable, sizeof (gpointer) * klass->vtable_size) == 0)) {
4798 mono_memory_barrier ();
4799 klass->vtable = klass->parent->vtable;
4801 MonoMethod **tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * klass->vtable_size);
4802 memcpy (tmp, vtable, sizeof (gpointer) * klass->vtable_size);
4803 mono_memory_barrier ();
4804 klass->vtable = tmp;
4807 DEBUG_INTERFACE_VTABLE (print_vtable_full (klass, klass->vtable, klass->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4808 if (mono_print_vtable) {
4811 print_implemented_interfaces (klass);
4813 for (i = 0; i <= max_iid; i++)
4814 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
4817 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&klass->byval_arg),
4818 klass->vtable_size, icount);
4820 for (i = 0; i < cur_slot; ++i) {
4825 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4826 mono_method_full_name (cm, TRUE));
4832 printf ("Interfaces %s.%s (max_iid = %d)\n", klass->name_space,
4833 klass->name, max_iid);
4835 for (i = 0; i < klass->interface_count; i++) {
4836 ic = klass->interfaces [i];
4837 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4838 mono_class_interface_offset (klass, ic),
4839 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4842 for (k = klass->parent; k ; k = k->parent) {
4843 for (i = 0; i < k->interface_count; i++) {
4844 ic = k->interfaces [i];
4845 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4846 mono_class_interface_offset (klass, ic),
4847 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4853 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (klass));
4858 char *name = mono_type_get_full_name (klass);
4859 mono_class_set_type_load_failure (klass, "VTable setup of type %s failed", name);
4862 g_hash_table_destroy (override_map);
4864 g_slist_free (virt_methods);
4869 * mono_method_get_vtable_slot:
4871 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4872 * LOCKING: Acquires the loader lock.
4874 * FIXME Use proper MonoError machinery here.
4877 mono_method_get_vtable_slot (MonoMethod *method)
4879 if (method->slot == -1) {
4880 mono_class_setup_vtable (method->klass);
4881 if (mono_class_has_failure (method->klass))
4883 if (method->slot == -1) {
4887 if (!method->klass->generic_class) {
4888 g_assert (method->is_inflated);
4889 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4892 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4893 g_assert (method->klass->generic_class);
4894 gklass = method->klass->generic_class->container_class;
4895 mono_class_setup_methods (method->klass);
4896 g_assert (method->klass->methods);
4897 for (i = 0; i < method->klass->method.count; ++i) {
4898 if (method->klass->methods [i] == method)
4901 g_assert (i < method->klass->method.count);
4902 g_assert (gklass->methods);
4903 method->slot = gklass->methods [i]->slot;
4905 g_assert (method->slot != -1);
4907 return method->slot;
4911 * mono_method_get_vtable_index:
4914 * Returns the index into the runtime vtable to access the method or,
4915 * in the case of a virtual generic method, the virtual generic method
4916 * thunk. Returns -1 on failure.
4918 * FIXME Use proper MonoError machinery here.
4921 mono_method_get_vtable_index (MonoMethod *method)
4923 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4924 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4925 if (imethod->declaring->is_generic)
4926 return mono_method_get_vtable_slot (imethod->declaring);
4928 return mono_method_get_vtable_slot (method);
4931 static MonoMethod *default_ghc = NULL;
4932 static MonoMethod *default_finalize = NULL;
4933 static int finalize_slot = -1;
4934 static int ghc_slot = -1;
4937 initialize_object_slots (MonoClass *klass)
4942 if (klass == mono_defaults.object_class) {
4943 mono_class_setup_vtable (klass);
4944 for (i = 0; i < klass->vtable_size; ++i) {
4945 MonoMethod *cm = klass->vtable [i];
4947 if (!strcmp (cm->name, "GetHashCode"))
4949 else if (!strcmp (cm->name, "Finalize"))
4953 g_assert (ghc_slot > 0);
4954 default_ghc = klass->vtable [ghc_slot];
4956 g_assert (finalize_slot > 0);
4957 default_finalize = klass->vtable [finalize_slot];
4962 MonoMethod *array_method;
4964 } GenericArrayMethodInfo;
4966 static int generic_array_method_num = 0;
4967 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4970 generic_array_methods (MonoClass *klass)
4972 int i, count_generic = 0;
4973 GList *list = NULL, *tmp;
4974 if (generic_array_method_num)
4975 return generic_array_method_num;
4976 mono_class_setup_methods (klass->parent); /*This is setting up System.Array*/
4977 g_assert (!mono_class_has_failure (klass->parent)); /*So hitting this assert is a huge problem*/
4978 for (i = 0; i < klass->parent->method.count; i++) {
4979 MonoMethod *m = klass->parent->methods [i];
4980 if (!strncmp (m->name, "InternalArray__", 15)) {
4982 list = g_list_prepend (list, m);
4985 list = g_list_reverse (list);
4986 generic_array_method_info = (GenericArrayMethodInfo *)mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4988 for (tmp = list; tmp; tmp = tmp->next) {
4989 const char *mname, *iname;
4991 MonoMethod *m = (MonoMethod *)tmp->data;
4992 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4993 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4995 generic_array_method_info [i].array_method = m;
4996 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4997 iname = "System.Collections.Generic.ICollection`1.";
4998 mname = m->name + 27;
4999 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
5000 iname = "System.Collections.Generic.IEnumerable`1.";
5001 mname = m->name + 27;
5002 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
5003 iname = "System.Collections.Generic.IReadOnlyList`1.";
5004 mname = m->name + strlen (ireadonlylist_prefix);
5005 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
5006 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
5007 mname = m->name + strlen (ireadonlycollection_prefix);
5008 } else if (!strncmp (m->name, "InternalArray__", 15)) {
5009 iname = "System.Collections.Generic.IList`1.";
5010 mname = m->name + 15;
5012 g_assert_not_reached ();
5015 name = (gchar *)mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
5016 strcpy (name, iname);
5017 strcpy (name + strlen (iname), mname);
5018 generic_array_method_info [i].name = name;
5021 /*g_print ("array generic methods: %d\n", count_generic);*/
5023 generic_array_method_num = count_generic;
5025 return generic_array_method_num;
5029 setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos)
5031 MonoGenericContext tmp_context;
5034 tmp_context.class_inst = NULL;
5035 tmp_context.method_inst = iface->generic_class->context.class_inst;
5036 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
5038 for (i = 0; i < generic_array_method_num; i++) {
5040 MonoMethod *m = generic_array_method_info [i].array_method;
5041 MonoMethod *inflated;
5043 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
5044 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
5045 methods [pos++] = mono_marshal_get_generic_array_helper (klass, iface, generic_array_method_info [i].name, inflated);
5050 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
5052 int null_length = strlen ("(null)");
5053 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
5054 char *s = (char *)mono_image_alloc (image, len);
5057 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
5058 g_assert (result == len - 1);
5065 * @class: the class to initialize
5067 * Compute the instance_size, class_size and other infos that cannot be
5068 * computed at mono_class_get() time. Also compute vtable_size if possible.
5069 * Returns TRUE on success or FALSE if there was a problem in loading
5070 * the type (incorrect assemblies, missing assemblies, methods, etc).
5072 * LOCKING: Acquires the loader lock.
5075 mono_class_init (MonoClass *klass)
5078 MonoCachedClassInfo cached_info;
5079 gboolean has_cached_info;
5083 /* Double-checking locking pattern */
5084 if (klass->inited || mono_class_has_failure (klass))
5085 return !mono_class_has_failure (klass);
5087 /*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/
5089 /* We do everything inside the lock to prevent races */
5090 mono_loader_lock ();
5092 if (klass->inited || mono_class_has_failure (klass)) {
5093 mono_loader_unlock ();
5094 /* Somebody might have gotten in before us */
5095 return !mono_class_has_failure (klass);
5098 if (klass->init_pending) {
5099 mono_class_set_type_load_failure (klass, "Recursive type definition detected");
5103 klass->init_pending = 1;
5105 if (mono_verifier_is_enabled_for_class (klass) && !mono_verifier_verify_class (klass)) {
5106 mono_class_set_type_load_failure (klass, "%s", concat_two_strings_with_zero (klass->image, klass->name, klass->image->assembly_name));
5111 if (klass->byval_arg.type == MONO_TYPE_ARRAY || klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5112 MonoClass *element_class = klass->element_class;
5113 if (!element_class->inited)
5114 mono_class_init (element_class);
5115 if (mono_class_set_type_load_failure_causedby_class (klass, element_class, "Could not load array element class"))
5119 mono_stats.initialized_class_count++;
5121 if (klass->generic_class && !klass->generic_class->is_dynamic) {
5122 MonoClass *gklass = klass->generic_class->container_class;
5124 mono_stats.generic_class_count++;
5126 klass->method = gklass->method;
5127 klass->field = gklass->field;
5129 mono_class_init (gklass);
5130 // FIXME: Why is this needed ?
5131 if (!mono_class_has_failure (gklass))
5132 mono_class_setup_methods (gklass);
5133 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic Type Definition failed to init"))
5136 if (MONO_CLASS_IS_INTERFACE (klass))
5137 klass->interface_id = mono_get_unique_iid (klass);
5140 if (klass->parent && !klass->parent->inited)
5141 mono_class_init (klass->parent);
5143 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
5145 if (klass->generic_class || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
5146 klass->nested_classes_inited = TRUE;
5149 * Computes the size used by the fields, and their locations
5151 if (has_cached_info) {
5152 klass->instance_size = cached_info.instance_size;
5153 klass->sizes.class_size = cached_info.class_size;
5154 klass->packing_size = cached_info.packing_size;
5155 klass->min_align = cached_info.min_align;
5156 klass->blittable = cached_info.blittable;
5157 klass->has_references = cached_info.has_references;
5158 klass->has_static_refs = cached_info.has_static_refs;
5159 klass->no_special_static_fields = cached_info.no_special_static_fields;
5162 if (!klass->size_inited){
5163 mono_class_setup_fields (klass);
5164 if (mono_class_has_failure (klass))
5168 /* Initialize arrays */
5170 klass->method.count = 3 + (klass->rank > 1? 2: 1);
5172 if (klass->interface_count) {
5173 int count_generic = generic_array_methods (klass);
5174 klass->method.count += klass->interface_count * count_generic;
5178 mono_class_setup_supertypes (klass);
5181 initialize_object_slots (klass);
5184 * Initialize the rest of the data without creating a generic vtable if possible.
5185 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5186 * also avoid computing a generic vtable.
5188 if (has_cached_info) {
5190 klass->vtable_size = cached_info.vtable_size;
5191 klass->has_finalize = cached_info.has_finalize;
5192 klass->has_finalize_inited = TRUE;
5193 klass->ghcimpl = cached_info.ghcimpl;
5194 klass->has_cctor = cached_info.has_cctor;
5195 } else if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5196 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5197 * The first slot if for array with.
5199 static int szarray_vtable_size[2] = { 0 };
5201 int slot = MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg) ? 0 : 1;
5204 if (!szarray_vtable_size [slot]) {
5205 mono_class_setup_vtable (klass);
5206 szarray_vtable_size [slot] = klass->vtable_size;
5208 klass->vtable_size = szarray_vtable_size[slot];
5210 } else if (klass->generic_class && !MONO_CLASS_IS_INTERFACE (klass)) {
5211 MonoClass *gklass = klass->generic_class->container_class;
5213 /* Generic instance case */
5214 klass->ghcimpl = gklass->ghcimpl;
5215 klass->has_cctor = gklass->has_cctor;
5217 mono_class_setup_vtable (gklass);
5218 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to init"))
5221 klass->vtable_size = gklass->vtable_size;
5225 /* ghcimpl is not currently used
5227 if (klass->parent) {
5228 MonoMethod *cmethod = klass->vtable [ghc_slot];
5229 if (cmethod->is_inflated)
5230 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5231 if (cmethod == default_ghc) {
5237 /* C# doesn't allow interfaces to have cctors */
5238 if (!MONO_CLASS_IS_INTERFACE (klass) || klass->image != mono_defaults.corlib) {
5239 MonoMethod *cmethod = NULL;
5241 if (klass->type_token && !image_is_dynamic(klass->image)) {
5242 cmethod = find_method_in_metadata (klass, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5243 /* The find_method function ignores the 'flags' argument */
5244 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5245 klass->has_cctor = 1;
5247 mono_class_setup_methods (klass);
5248 if (mono_class_has_failure (klass))
5251 for (i = 0; i < klass->method.count; ++i) {
5252 MonoMethod *method = klass->methods [i];
5253 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5254 (strcmp (".cctor", method->name) == 0)) {
5255 klass->has_cctor = 1;
5263 if (klass->parent) {
5264 MonoError parent_error;
5265 mono_error_init (&parent_error);
5266 int first_iface_slot;
5267 /* This will compute klass->parent->vtable_size for some classes */
5268 mono_class_init (klass->parent);
5269 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class failed to initialize")) {
5272 if (!klass->parent->vtable_size) {
5273 /* FIXME: Get rid of this somehow */
5274 mono_class_setup_vtable (klass->parent);
5275 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class vtable failed to initialize")) {
5279 first_iface_slot = klass->parent->vtable_size;
5280 if (mono_class_need_stelemref_method (klass))
5282 setup_interface_offsets (klass, first_iface_slot, TRUE);
5284 setup_interface_offsets (klass, 0, TRUE);
5287 if (mono_security_core_clr_enabled ())
5288 mono_security_core_clr_check_inheritance (klass);
5290 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass))
5291 mono_class_set_type_load_failure (klass, "Invalid generic instantiation");
5296 /* Because of the double-checking locking pattern */
5297 mono_memory_barrier ();
5299 klass->init_pending = 0;
5301 mono_loader_unlock ();
5303 return !mono_class_has_failure (klass);
5307 * mono_class_has_finalizer:
5309 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5313 mono_class_has_finalizer (MonoClass *klass)
5315 gboolean has_finalize = FALSE;
5317 if (klass->has_finalize_inited)
5318 return klass->has_finalize;
5320 /* Interfaces and valuetypes are not supposed to have finalizers */
5321 if (!(MONO_CLASS_IS_INTERFACE (klass) || klass->valuetype)) {
5322 MonoMethod *cmethod = NULL;
5324 if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5325 } else if (klass->generic_class) {
5326 MonoClass *gklass = klass->generic_class->container_class;
5328 has_finalize = mono_class_has_finalizer (gklass);
5329 } else if (klass->parent && klass->parent->has_finalize) {
5330 has_finalize = TRUE;
5332 if (klass->parent) {
5334 * Can't search in metadata for a method named Finalize, because that
5335 * ignores overrides.
5337 mono_class_setup_vtable (klass);
5338 if (mono_class_has_failure (klass))
5341 cmethod = klass->vtable [finalize_slot];
5345 g_assert (klass->vtable_size > finalize_slot);
5347 if (klass->parent) {
5348 if (cmethod->is_inflated)
5349 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5350 if (cmethod != default_finalize)
5351 has_finalize = TRUE;
5357 mono_image_lock (klass->image);
5359 if (!klass->has_finalize_inited) {
5360 klass->has_finalize = has_finalize ? 1 : 0;
5362 mono_memory_barrier ();
5363 klass->has_finalize_inited = TRUE;
5366 mono_image_unlock (klass->image);
5368 return klass->has_finalize;
5372 mono_is_corlib_image (MonoImage *image)
5374 /* FIXME: allow the dynamic case for our compilers and with full trust */
5375 if (image_is_dynamic (image))
5376 return image->assembly && !strcmp (image->assembly->aname.name, "mscorlib");
5378 return image == mono_defaults.corlib;
5382 * LOCKING: this assumes the loader lock is held
5385 mono_class_setup_mono_type (MonoClass *klass)
5387 const char *name = klass->name;
5388 const char *nspace = klass->name_space;
5389 gboolean is_corlib = mono_is_corlib_image (klass->image);
5391 klass->this_arg.byref = 1;
5392 klass->this_arg.data.klass = klass;
5393 klass->this_arg.type = MONO_TYPE_CLASS;
5394 klass->byval_arg.data.klass = klass;
5395 klass->byval_arg.type = MONO_TYPE_CLASS;
5397 if (is_corlib && !strcmp (nspace, "System")) {
5398 if (!strcmp (name, "ValueType")) {
5400 * do not set the valuetype bit for System.ValueType.
5401 * klass->valuetype = 1;
5403 klass->blittable = TRUE;
5404 } else if (!strcmp (name, "Enum")) {
5406 * do not set the valuetype bit for System.Enum.
5407 * klass->valuetype = 1;
5409 klass->valuetype = 0;
5410 klass->enumtype = 0;
5411 } else if (!strcmp (name, "Object")) {
5412 klass->byval_arg.type = MONO_TYPE_OBJECT;
5413 klass->this_arg.type = MONO_TYPE_OBJECT;
5414 } else if (!strcmp (name, "String")) {
5415 klass->byval_arg.type = MONO_TYPE_STRING;
5416 klass->this_arg.type = MONO_TYPE_STRING;
5417 } else if (!strcmp (name, "TypedReference")) {
5418 klass->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5419 klass->this_arg.type = MONO_TYPE_TYPEDBYREF;
5423 if (klass->valuetype) {
5424 int t = MONO_TYPE_VALUETYPE;
5426 if (is_corlib && !strcmp (nspace, "System")) {
5429 if (!strcmp (name, "Boolean")) {
5430 t = MONO_TYPE_BOOLEAN;
5431 } else if (!strcmp(name, "Byte")) {
5433 klass->blittable = TRUE;
5437 if (!strcmp (name, "Char")) {
5442 if (!strcmp (name, "Double")) {
5444 klass->blittable = TRUE;
5448 if (!strcmp (name, "Int32")) {
5450 klass->blittable = TRUE;
5451 } else if (!strcmp(name, "Int16")) {
5453 klass->blittable = TRUE;
5454 } else if (!strcmp(name, "Int64")) {
5456 klass->blittable = TRUE;
5457 } else if (!strcmp(name, "IntPtr")) {
5459 klass->blittable = TRUE;
5463 if (!strcmp (name, "Single")) {
5465 klass->blittable = TRUE;
5466 } else if (!strcmp(name, "SByte")) {
5468 klass->blittable = TRUE;
5472 if (!strcmp (name, "UInt32")) {
5474 klass->blittable = TRUE;
5475 } else if (!strcmp(name, "UInt16")) {
5477 klass->blittable = TRUE;
5478 } else if (!strcmp(name, "UInt64")) {
5480 klass->blittable = TRUE;
5481 } else if (!strcmp(name, "UIntPtr")) {
5483 klass->blittable = TRUE;
5487 if (!strcmp (name, "TypedReference")) {
5488 t = MONO_TYPE_TYPEDBYREF;
5489 klass->blittable = TRUE;
5493 if (!strcmp (name, "Void")) {
5501 klass->byval_arg.type = (MonoTypeEnum)t;
5502 klass->this_arg.type = (MonoTypeEnum)t;
5505 if (MONO_CLASS_IS_INTERFACE (klass))
5506 klass->interface_id = mono_get_unique_iid (klass);
5512 * COM initialization is delayed until needed.
5513 * However when a [ComImport] attribute is present on a type it will trigger
5514 * the initialization. This is not a problem unless the BCL being executed
5515 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5518 init_com_from_comimport (MonoClass *klass)
5520 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5521 if (mono_security_core_clr_enabled ()) {
5522 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5523 if (!mono_security_core_clr_determine_platform_image (klass->image)) {
5524 /* but it can not be made available for application (i.e. user code) since all COM calls
5525 * are considered native calls. In this case we fail with a TypeLoadException (just like
5526 * Silverlight 2 does */
5527 mono_class_set_type_load_failure (klass, "");
5532 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5534 #endif /*DISABLE_COM*/
5537 * LOCKING: this assumes the loader lock is held
5540 mono_class_setup_parent (MonoClass *klass, MonoClass *parent)
5542 gboolean system_namespace;
5543 gboolean is_corlib = mono_is_corlib_image (klass->image);
5545 system_namespace = !strcmp (klass->name_space, "System") && is_corlib;
5547 /* if root of the hierarchy */
5548 if (system_namespace && !strcmp (klass->name, "Object")) {
5549 klass->parent = NULL;
5550 klass->instance_size = sizeof (MonoObject);
5553 if (!strcmp (klass->name, "<Module>")) {
5554 klass->parent = NULL;
5555 klass->instance_size = 0;
5559 if (!MONO_CLASS_IS_INTERFACE (klass)) {
5560 /* Imported COM Objects always derive from __ComObject. */
5562 if (MONO_CLASS_IS_IMPORT (klass)) {
5563 init_com_from_comimport (klass);
5564 if (parent == mono_defaults.object_class)
5565 parent = mono_class_get_com_object_class ();
5569 /* set the parent to something useful and safe, but mark the type as broken */
5570 parent = mono_defaults.object_class;
5571 mono_class_set_type_load_failure (klass, "");
5574 klass->parent = parent;
5576 if (parent->generic_class && !parent->name) {
5578 * If the parent is a generic instance, we may get
5579 * called before it is fully initialized, especially
5580 * before it has its name.
5585 #ifndef DISABLE_REMOTING
5586 klass->marshalbyref = parent->marshalbyref;
5587 klass->contextbound = parent->contextbound;
5590 klass->delegate = parent->delegate;
5592 if (MONO_CLASS_IS_IMPORT (klass) || mono_class_is_com_object (parent))
5593 mono_class_set_is_com_object (klass);
5595 if (system_namespace) {
5596 #ifndef DISABLE_REMOTING
5597 if (klass->name [0] == 'M' && !strcmp (klass->name, "MarshalByRefObject"))
5598 klass->marshalbyref = 1;
5600 if (klass->name [0] == 'C' && !strcmp (klass->name, "ContextBoundObject"))
5601 klass->contextbound = 1;
5603 if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate"))
5604 klass->delegate = 1;
5607 if (klass->parent->enumtype || (mono_is_corlib_image (klass->parent->image) && (strcmp (klass->parent->name, "ValueType") == 0) &&
5608 (strcmp (klass->parent->name_space, "System") == 0)))
5609 klass->valuetype = 1;
5610 if (mono_is_corlib_image (klass->parent->image) && ((strcmp (klass->parent->name, "Enum") == 0) && (strcmp (klass->parent->name_space, "System") == 0))) {
5611 klass->valuetype = klass->enumtype = 1;
5613 /*klass->enumtype = klass->parent->enumtype; */
5615 /* initialize com types if COM interfaces are present */
5617 if (MONO_CLASS_IS_IMPORT (klass))
5618 init_com_from_comimport (klass);
5620 klass->parent = NULL;
5626 * mono_class_setup_supertypes:
5629 * Build the data structure needed to make fast type checks work.
5630 * This currently sets two fields in @class:
5631 * - idepth: distance between @class and System.Object in the type
5633 * - supertypes: array of classes: each element has a class in the hierarchy
5634 * starting from @class up to System.Object
5636 * LOCKING: This function is atomic, in case of contention we waste memory.
5639 mono_class_setup_supertypes (MonoClass *klass)
5642 MonoClass **supertypes;
5644 mono_atomic_load_acquire (supertypes, MonoClass **, &klass->supertypes);
5648 if (klass->parent && !klass->parent->supertypes)
5649 mono_class_setup_supertypes (klass->parent);
5651 klass->idepth = klass->parent->idepth + 1;
5655 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, klass->idepth);
5656 supertypes = (MonoClass **)mono_class_alloc0 (klass, sizeof (MonoClass *) * ms);
5658 if (klass->parent) {
5659 CHECKED_METADATA_WRITE_PTR ( supertypes [klass->idepth - 1] , klass );
5662 for (supertype_idx = 0; supertype_idx < klass->parent->idepth; supertype_idx++)
5663 CHECKED_METADATA_WRITE_PTR ( supertypes [supertype_idx] , klass->parent->supertypes [supertype_idx] );
5665 CHECKED_METADATA_WRITE_PTR ( supertypes [0] , klass );
5668 CHECKED_METADATA_WRITE_PTR_ATOMIC ( klass->supertypes , supertypes );
5672 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5674 MonoClass *gtd = (MonoClass*)user_data;
5675 /* Only try to fix generic instances of @gtd */
5676 if (gclass->generic_class->container_class != gtd)
5679 /* Check if the generic instance has no parent. */
5680 if (gtd->parent && !gclass->parent)
5681 mono_generic_class_setup_parent (gclass, gtd);
5687 mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char *msg)
5689 mono_class_set_type_load_failure (klass, "%s", msg);
5690 mono_error_set_type_load_class (error, klass, "%s", msg);
5694 * mono_class_create_from_typedef:
5695 * @image: image where the token is valid
5696 * @type_token: typedef token
5697 * @error: used to return any error found while creating the type
5699 * Create the MonoClass* representing the specified type token.
5700 * @type_token must be a TypeDef token.
5702 * FIXME: don't return NULL on failure, just the the caller figure it out.
5705 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5707 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5708 MonoClass *klass, *parent = NULL;
5709 guint32 cols [MONO_TYPEDEF_SIZE];
5710 guint32 cols_next [MONO_TYPEDEF_SIZE];
5711 guint tidx = mono_metadata_token_index (type_token);
5712 MonoGenericContext *context = NULL;
5713 const char *name, *nspace;
5715 MonoClass **interfaces;
5716 guint32 field_last, method_last;
5717 guint32 nesting_tokeen;
5719 mono_error_init (error);
5721 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5722 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5726 mono_loader_lock ();
5728 if ((klass = (MonoClass *)mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5729 mono_loader_unlock ();
5733 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5735 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5736 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5738 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
5741 klass->name_space = nspace;
5743 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5745 klass->image = image;
5746 klass->type_token = type_token;
5747 klass->flags = cols [MONO_TYPEDEF_FLAGS];
5749 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
5751 classes_size += sizeof (MonoClass);
5754 * Check whether we're a generic type definition.
5756 klass->generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
5757 if (klass->generic_container) {
5758 klass->is_generic = 1;
5759 klass->generic_container->owner.klass = klass;
5760 klass->generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
5761 context = &klass->generic_container->context;
5764 if (klass->generic_container)
5765 enable_gclass_recording ();
5767 if (cols [MONO_TYPEDEF_EXTENDS]) {
5769 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5771 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5772 /*WARNING: this must satisfy mono_metadata_type_hash*/
5773 klass->this_arg.byref = 1;
5774 klass->this_arg.data.klass = klass;
5775 klass->this_arg.type = MONO_TYPE_CLASS;
5776 klass->byval_arg.data.klass = klass;
5777 klass->byval_arg.type = MONO_TYPE_CLASS;
5779 parent = mono_class_get_checked (image, parent_token, error);
5780 if (parent && context) /* Always inflate */
5781 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5783 if (parent == NULL) {
5784 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5785 goto parent_failure;
5788 for (tmp = parent; tmp; tmp = tmp->parent) {
5790 mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
5791 goto parent_failure;
5793 if (klass->generic_container && tmp->generic_class && tmp->generic_class->container_class == klass) {
5794 mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
5795 goto parent_failure;
5800 mono_class_setup_parent (klass, parent);
5802 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5803 mono_class_setup_mono_type (klass);
5805 if (klass->generic_container)
5806 disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
5809 * This might access klass->byval_arg for recursion generated by generic constraints,
5810 * so it has to come after setup_mono_type ().
5812 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5813 klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5814 if (!mono_error_ok (error)) {
5815 /*FIXME implement a mono_class_set_failure_from_mono_error */
5816 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5817 mono_loader_unlock ();
5818 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5823 if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5827 if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5831 klass->cast_class = klass->element_class = klass;
5833 if (!klass->enumtype) {
5834 if (!mono_metadata_interfaces_from_typedef_full (
5835 image, type_token, &interfaces, &icount, FALSE, context, error)){
5837 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5838 mono_loader_unlock ();
5839 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5843 klass->interfaces = interfaces;
5844 klass->interface_count = icount;
5845 klass->interfaces_inited = 1;
5848 /*g_print ("Load class %s\n", name);*/
5851 * Compute the field and method lists
5853 klass->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5854 klass->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5856 if (tt->rows > tidx){
5857 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5858 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5859 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5861 field_last = image->tables [MONO_TABLE_FIELD].rows;
5862 method_last = image->tables [MONO_TABLE_METHOD].rows;
5865 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5866 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5867 klass->field.count = field_last - klass->field.first;
5869 klass->field.count = 0;
5871 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5872 klass->method.count = method_last - klass->method.first;
5874 klass->method.count = 0;
5876 /* reserve space to store vector pointer in arrays */
5877 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5878 klass->instance_size += 2 * sizeof (gpointer);
5879 g_assert (klass->field.count == 0);
5882 if (klass->enumtype) {
5883 MonoType *enum_basetype = mono_class_find_enum_basetype (klass, error);
5884 if (!enum_basetype) {
5885 /*set it to a default value as the whole runtime can't handle this to be null*/
5886 klass->cast_class = klass->element_class = mono_defaults.int32_class;
5887 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5888 mono_loader_unlock ();
5889 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5892 klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
5896 * If we're a generic type definition, load the constraints.
5897 * We must do this after the class has been constructed to make certain recursive scenarios
5900 if (klass->generic_container && !mono_metadata_load_generic_param_constraints_checked (image, type_token, klass->generic_container, error)) {
5901 mono_class_set_type_load_failure (klass, "Could not load generic parameter constrains due to %s", mono_error_get_message (error));
5902 mono_loader_unlock ();
5903 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5907 if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5908 if (!strncmp (name, "Vector", 6))
5909 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");
5912 mono_loader_unlock ();
5914 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5919 mono_class_setup_mono_type (klass);
5920 mono_loader_unlock ();
5921 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5925 /** Is klass a Nullable<T> ginst? */
5927 mono_class_is_nullable (MonoClass *klass)
5929 return klass->generic_class != NULL &&
5930 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5934 /** if klass is T? return T */
5936 mono_class_get_nullable_param (MonoClass *klass)
5938 g_assert (mono_class_is_nullable (klass));
5939 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5943 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5947 MonoGenericClass *gclass = klass->generic_class;
5949 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5950 if (!mono_error_ok (&error)) {
5951 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5952 klass->parent = mono_defaults.object_class;
5953 mono_class_set_type_load_failure (klass, "Parent is a generic type instantiation that failed due to: %s", mono_error_get_message (&error));
5954 mono_error_cleanup (&error);
5958 mono_class_setup_parent (klass, klass->parent);
5960 if (klass->enumtype) {
5961 klass->cast_class = gtd->cast_class;
5962 klass->element_class = gtd->element_class;
5968 * Create the `MonoClass' for an instantiation of a generic type.
5969 * We only do this if we actually need it.
5972 mono_generic_class_get_class (MonoGenericClass *gclass)
5974 MonoClass *klass, *gklass;
5976 if (gclass->cached_class)
5977 return gclass->cached_class;
5979 mono_loader_lock ();
5980 if (gclass->cached_class) {
5981 mono_loader_unlock ();
5982 return gclass->cached_class;
5985 klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
5987 gklass = gclass->container_class;
5989 if (record_gclass_instantiation > 0)
5990 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
5992 if (gklass->nested_in) {
5993 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
5994 klass->nested_in = gklass->nested_in;
5997 klass->name = gklass->name;
5998 klass->name_space = gklass->name_space;
6000 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6002 klass->image = gklass->image;
6003 klass->flags = gklass->flags;
6004 klass->type_token = gklass->type_token;
6005 klass->field.count = gklass->field.count;
6007 klass->is_inflated = 1;
6008 klass->generic_class = gclass;
6010 klass->byval_arg.type = MONO_TYPE_GENERICINST;
6011 klass->this_arg.type = klass->byval_arg.type;
6012 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
6013 klass->this_arg.byref = TRUE;
6014 klass->enumtype = gklass->enumtype;
6015 klass->valuetype = gklass->valuetype;
6017 klass->cast_class = klass->element_class = klass;
6019 if (mono_class_is_nullable (klass))
6020 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
6023 * We're not interested in the nested classes of a generic instance.
6024 * We use the generic type definition to look for nested classes.
6027 mono_generic_class_setup_parent (klass, gklass);
6029 if (gclass->is_dynamic) {
6031 * 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.
6032 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
6033 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
6035 if (!gklass->wastypebuilder)
6038 mono_class_setup_supertypes (klass);
6040 if (klass->enumtype) {
6042 * For enums, gklass->fields might not been set, but instance_size etc. is
6043 * already set in mono_reflection_create_internal_class (). For non-enums,
6044 * these will be computed normally in mono_class_layout_fields ().
6046 klass->instance_size = gklass->instance_size;
6047 klass->sizes.class_size = gklass->sizes.class_size;
6048 mono_memory_barrier ();
6049 klass->size_inited = 1;
6053 mono_memory_barrier ();
6054 gclass->cached_class = klass;
6056 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6058 inflated_classes ++;
6059 inflated_classes_size += sizeof (MonoClass);
6061 mono_loader_unlock ();
6067 get_image_for_container (MonoGenericContainer *container)
6070 if (container->is_anonymous) {
6071 result = container->owner.image;
6074 if (container->is_method) {
6075 MonoMethod *method = container->owner.method;
6076 g_assert_checked (method);
6077 klass = method->klass;
6079 klass = container->owner.klass;
6081 g_assert_checked (klass);
6082 result = klass->image;
6089 get_image_for_generic_param (MonoGenericParam *param)
6091 MonoGenericContainer *container = mono_generic_param_owner (param);
6092 g_assert_checked (container);
6093 return get_image_for_container (container);
6096 // Make a string in the designated image consisting of a single integer.
6097 #define INT_STRING_SIZE 16
6099 make_generic_name_string (MonoImage *image, int num)
6101 char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
6102 g_snprintf (name, INT_STRING_SIZE, "%d", num);
6106 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
6107 // pinfo is derived from param by the caller for us.
6109 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
6111 MonoClass *klass, **ptr;
6113 MonoGenericContainer *container = mono_generic_param_owner (param);
6114 g_assert_checked (container);
6116 MonoImage *image = get_image_for_container (container);
6117 gboolean is_mvar = container->is_method;
6118 gboolean is_anonymous = container->is_anonymous;
6120 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6121 classes_size += sizeof (MonoClass);
6124 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
6126 int n = mono_generic_param_num (param);
6127 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
6131 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , "" );
6132 } else if (is_mvar) {
6133 MonoMethod *omethod = container->owner.method;
6134 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
6136 MonoClass *oklass = container->owner.klass;
6137 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
6140 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6142 // Count non-NULL items in pinfo->constraints
6145 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6149 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6150 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
6152 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
6153 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
6155 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
6158 if (count - pos > 0) {
6159 klass->interface_count = count - pos;
6160 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
6161 klass->interfaces_inited = TRUE;
6162 for (i = pos; i < count; i++)
6163 CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
6166 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
6168 klass->inited = TRUE;
6169 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class , klass );
6170 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
6171 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
6173 klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6174 klass->this_arg.type = klass->byval_arg.type;
6175 CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param , param );
6176 CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
6177 klass->this_arg.byref = TRUE;
6179 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6180 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6182 /*Init these fields to sane values*/
6183 klass->min_align = 1;
6185 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6186 * constrained to, the JIT depends on this.
6188 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6189 mono_memory_barrier ();
6190 klass->size_inited = 1;
6191 klass->setup_fields_called = 1;
6193 mono_class_setup_supertypes (klass);
6195 if (count - pos > 0) {
6196 mono_class_setup_vtable (klass->parent);
6197 if (mono_class_has_failure (klass->parent))
6198 mono_class_set_type_load_failure (klass, "Failed to setup parent interfaces");
6200 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6206 #define FAST_CACHE_SIZE 16
6209 * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6210 * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6211 * we cache the MonoClasses.
6212 * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6213 * LOCKING: Takes the image lock depending on @take_lock.
6216 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6218 int n = mono_generic_param_num (param);
6219 MonoImage *image = get_image_for_generic_param (param);
6220 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6221 MonoClass *klass = NULL;
6226 // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6227 // For high numbers or constraints we have to use pointer hashes.
6228 if (param->gshared_constraint) {
6229 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6232 mono_image_lock (image);
6233 klass = (MonoClass *)g_hash_table_lookup (ht, param);
6235 mono_image_unlock (image);
6240 if (n < FAST_CACHE_SIZE) {
6242 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6244 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6246 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6249 mono_image_lock (image);
6250 klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6252 mono_image_unlock (image);
6259 * LOCKING: Image lock (param->image) must be held
6262 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6264 int n = mono_generic_param_num (param);
6265 MonoImage *image = get_image_for_generic_param (param);
6266 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6270 if (param->gshared_constraint) {
6271 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6273 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6274 mono_memory_barrier ();
6276 image->mvar_cache_constrained = ht;
6278 image->var_cache_constrained = ht;
6280 g_hash_table_insert (ht, param, klass);
6281 } else if (n < FAST_CACHE_SIZE) {
6283 /* Requires locking to avoid droping an already published class */
6284 if (!image->mvar_cache_fast)
6285 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6286 image->mvar_cache_fast [n] = klass;
6288 if (!image->var_cache_fast)
6289 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6290 image->var_cache_fast [n] = klass;
6293 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6295 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6297 ht = g_hash_table_new (NULL, NULL);
6298 mono_memory_barrier ();
6300 image->mvar_cache_slow = ht;
6302 image->var_cache_slow = ht;
6305 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6310 * LOCKING: Acquires the image lock (@image).
6313 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6315 MonoImage *image = get_image_for_generic_param (param);
6316 MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6317 MonoClass *klass, *klass2;
6319 // If a klass already exists for this object and is cached, return it.
6320 if (pinfo) // Non-anonymous
6321 klass = pinfo->pklass;
6323 klass = get_anon_gparam_class (param, TRUE);
6328 // Create a new klass
6329 klass = make_generic_param_class (param, pinfo);
6331 // Now we need to cache the klass we created.
6332 // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6333 // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6334 // and allow our newly-created klass object to just leak.
6335 mono_memory_barrier ();
6337 mono_image_lock (image);
6339 // Here "klass2" refers to the klass potentially created by the other thread.
6340 if (pinfo) // Repeat check from above
6341 klass2 = pinfo->pklass;
6343 klass2 = get_anon_gparam_class (param, FALSE);
6350 pinfo->pklass = klass;
6352 set_anon_gparam_class (param, klass);
6354 mono_image_unlock (image);
6356 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6358 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED); // Alert profiler about botched class create
6360 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6366 * mono_class_from_generic_parameter:
6367 * @param: Parameter to find/construct a class for.
6368 * @arg2: Is ignored.
6369 * @arg3: Is ignored.
6372 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6374 return mono_class_from_generic_parameter_internal (param);
6379 mono_ptr_class_get (MonoType *type)
6382 MonoClass *el_class;
6386 el_class = mono_class_from_mono_type (type);
6387 image = el_class->image;
6389 mono_image_lock (image);
6390 if (image->ptr_cache) {
6391 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6392 mono_image_unlock (image);
6396 mono_image_unlock (image);
6398 result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6400 classes_size += sizeof (MonoClass);
6402 result->parent = NULL; /* no parent for PTR types */
6403 result->name_space = el_class->name_space;
6404 name = g_strdup_printf ("%s*", el_class->name);
6405 result->name = mono_image_strdup (image, name);
6408 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6410 result->image = el_class->image;
6411 result->inited = TRUE;
6412 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6413 /* Can pointers get boxed? */
6414 result->instance_size = sizeof (gpointer);
6415 result->cast_class = result->element_class = el_class;
6416 result->blittable = TRUE;
6418 result->byval_arg.type = MONO_TYPE_PTR;
6419 result->this_arg.type = result->byval_arg.type;
6420 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6421 result->this_arg.byref = TRUE;
6423 mono_class_setup_supertypes (result);
6425 mono_image_lock (image);
6426 if (image->ptr_cache) {
6428 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6429 mono_image_unlock (image);
6430 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6434 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6436 g_hash_table_insert (image->ptr_cache, el_class, result);
6437 mono_image_unlock (image);
6439 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6445 mono_fnptr_class_get (MonoMethodSignature *sig)
6448 static GHashTable *ptr_hash = NULL;
6450 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6452 mono_loader_lock ();
6455 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6457 if ((result = (MonoClass *)g_hash_table_lookup (ptr_hash, sig))) {
6458 mono_loader_unlock ();
6461 result = g_new0 (MonoClass, 1);
6463 result->parent = NULL; /* no parent for PTR types */
6464 result->name_space = "System";
6465 result->name = "MonoFNPtrFakeClass";
6467 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6469 result->image = mono_defaults.corlib; /* need to fix... */
6470 result->inited = TRUE;
6471 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6472 /* Can pointers get boxed? */
6473 result->instance_size = sizeof (gpointer);
6474 result->cast_class = result->element_class = result;
6475 result->blittable = TRUE;
6477 result->byval_arg.type = MONO_TYPE_FNPTR;
6478 result->this_arg.type = result->byval_arg.type;
6479 result->this_arg.data.method = result->byval_arg.data.method = sig;
6480 result->this_arg.byref = TRUE;
6481 result->blittable = TRUE;
6483 mono_class_setup_supertypes (result);
6485 g_hash_table_insert (ptr_hash, sig, result);
6487 mono_loader_unlock ();
6489 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6495 * mono_class_from_mono_type:
6496 * @type: describes the type to return
6498 * This returns a MonoClass for the specified MonoType, the value is never NULL.
6501 mono_class_from_mono_type (MonoType *type)
6503 switch (type->type) {
6504 case MONO_TYPE_OBJECT:
6505 return type->data.klass? type->data.klass: mono_defaults.object_class;
6506 case MONO_TYPE_VOID:
6507 return type->data.klass? type->data.klass: mono_defaults.void_class;
6508 case MONO_TYPE_BOOLEAN:
6509 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6510 case MONO_TYPE_CHAR:
6511 return type->data.klass? type->data.klass: mono_defaults.char_class;
6513 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6515 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6517 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6519 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6521 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6523 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6525 return type->data.klass? type->data.klass: mono_defaults.int_class;
6527 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6529 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6531 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6533 return type->data.klass? type->data.klass: mono_defaults.single_class;
6535 return type->data.klass? type->data.klass: mono_defaults.double_class;
6536 case MONO_TYPE_STRING:
6537 return type->data.klass? type->data.klass: mono_defaults.string_class;
6538 case MONO_TYPE_TYPEDBYREF:
6539 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6540 case MONO_TYPE_ARRAY:
6541 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6543 return mono_ptr_class_get (type->data.type);
6544 case MONO_TYPE_FNPTR:
6545 return mono_fnptr_class_get (type->data.method);
6546 case MONO_TYPE_SZARRAY:
6547 return mono_array_class_get (type->data.klass, 1);
6548 case MONO_TYPE_CLASS:
6549 case MONO_TYPE_VALUETYPE:
6550 return type->data.klass;
6551 case MONO_TYPE_GENERICINST:
6552 return mono_generic_class_get_class (type->data.generic_class);
6553 case MONO_TYPE_MVAR:
6555 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6557 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6558 g_assert_not_reached ();
6561 // Yes, this returns NULL, even if it is documented as not doing so, but there
6562 // is no way for the code to make it this far, due to the assert above.
6567 * mono_type_retrieve_from_typespec
6568 * @image: context where the image is created
6569 * @type_spec: typespec token
6570 * @context: the generic context used to evaluate generic instantiations in
6573 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6575 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6577 *did_inflate = FALSE;
6582 if (context && (context->class_inst || context->method_inst)) {
6583 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6585 if (!mono_error_ok (error)) {
6591 *did_inflate = TRUE;
6598 * mono_class_create_from_typespec
6599 * @image: context where the image is created
6600 * @type_spec: typespec token
6601 * @context: the generic context used to evaluate generic instantiations in
6604 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6607 gboolean inflated = FALSE;
6608 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6609 return_val_if_nok (error, NULL);
6610 ret = mono_class_from_mono_type (t);
6612 mono_metadata_free_type (t);
6617 * mono_bounded_array_class_get:
6618 * @element_class: element class
6619 * @rank: the dimension of the array class
6620 * @bounded: whenever the array has non-zero bounds
6622 * Returns: A class object describing the array with element type @element_type and
6626 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6630 MonoClass *parent = NULL;
6631 GSList *list, *rootlist = NULL;
6634 gboolean corlib_type = FALSE;
6636 g_assert (rank <= 255);
6639 /* bounded only matters for one-dimensional arrays */
6642 image = eclass->image;
6644 if (rank == 1 && !bounded) {
6646 * This case is very frequent not just during compilation because of calls
6647 * from mono_class_from_mono_type (), mono_array_new (),
6648 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6650 mono_os_mutex_lock (&image->szarray_cache_lock);
6651 if (!image->szarray_cache)
6652 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6653 klass = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6654 mono_os_mutex_unlock (&image->szarray_cache_lock);
6658 mono_loader_lock ();
6660 mono_loader_lock ();
6662 if (!image->array_cache)
6663 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6665 if ((rootlist = list = (GSList *)g_hash_table_lookup (image->array_cache, eclass))) {
6666 for (; list; list = list->next) {
6667 klass = (MonoClass *)list->data;
6668 if ((klass->rank == rank) && (klass->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6669 mono_loader_unlock ();
6676 /* for the building corlib use System.Array from it */
6677 if (image->assembly && assembly_is_dynamic (image->assembly) && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6678 parent = mono_class_load_from_name (image, "System", "Array");
6681 parent = mono_defaults.array_class;
6682 if (!parent->inited)
6683 mono_class_init (parent);
6686 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6688 klass->image = image;
6689 klass->name_space = eclass->name_space;
6690 nsize = strlen (eclass->name);
6691 name = (char *)g_malloc (nsize + 2 + rank + 1);
6692 memcpy (name, eclass->name, nsize);
6695 memset (name + nsize + 1, ',', rank - 1);
6697 name [nsize + rank] = '*';
6698 name [nsize + rank + bounded] = ']';
6699 name [nsize + rank + bounded + 1] = 0;
6700 klass->name = mono_image_strdup (image, name);
6703 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6705 classes_size += sizeof (MonoClass);
6707 klass->type_token = 0;
6708 /* all arrays are marked serializable and sealed, bug #42779 */
6709 klass->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6710 klass->parent = parent;
6711 klass->instance_size = mono_class_instance_size (klass->parent);
6713 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6714 /*Arrays of those two types are invalid.*/
6715 MonoError prepared_error;
6716 mono_error_init (&prepared_error);
6717 mono_error_set_invalid_program (&prepared_error, "Arrays of void or System.TypedReference types are invalid.");
6718 mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6719 mono_error_cleanup (&prepared_error);
6720 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6721 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6722 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6723 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6725 /* element_size -1 is ok as this is not an instantitable type*/
6726 klass->sizes.element_size = -1;
6728 klass->sizes.element_size = mono_class_array_element_size (eclass);
6730 mono_class_setup_supertypes (klass);
6732 if (eclass->generic_class)
6733 mono_class_init (eclass);
6734 if (!eclass->size_inited)
6735 mono_class_setup_fields (eclass);
6736 mono_class_set_type_load_failure_causedby_class (klass, eclass, "Could not load array element type");
6737 /*FIXME we fail the array type, but we have to let other fields be set.*/
6739 klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6743 if (eclass->enumtype)
6744 klass->cast_class = eclass->element_class;
6746 klass->cast_class = eclass;
6748 switch (klass->cast_class->byval_arg.type) {
6750 klass->cast_class = mono_defaults.byte_class;
6753 klass->cast_class = mono_defaults.int16_class;
6756 #if SIZEOF_VOID_P == 4
6760 klass->cast_class = mono_defaults.int32_class;
6763 #if SIZEOF_VOID_P == 8
6767 klass->cast_class = mono_defaults.int64_class;
6773 klass->element_class = eclass;
6775 if ((rank > 1) || bounded) {
6776 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6777 klass->byval_arg.type = MONO_TYPE_ARRAY;
6778 klass->byval_arg.data.array = at;
6779 at->eklass = eclass;
6781 /* FIXME: complete.... */
6783 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6784 klass->byval_arg.data.klass = eclass;
6786 klass->this_arg = klass->byval_arg;
6787 klass->this_arg.byref = 1;
6792 klass->generic_container = eclass->generic_container;
6794 if (rank == 1 && !bounded) {
6795 MonoClass *prev_class;
6797 mono_os_mutex_lock (&image->szarray_cache_lock);
6798 prev_class = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6800 /* Someone got in before us */
6803 g_hash_table_insert (image->szarray_cache, eclass, klass);
6804 mono_os_mutex_unlock (&image->szarray_cache_lock);
6806 list = g_slist_append (rootlist, klass);
6807 g_hash_table_insert (image->array_cache, eclass, list);
6810 mono_loader_unlock ();
6812 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6818 * mono_array_class_get:
6819 * @element_class: element class
6820 * @rank: the dimension of the array class
6822 * Returns: A class object describing the array with element type @element_type and
6826 mono_array_class_get (MonoClass *eclass, guint32 rank)
6828 return mono_bounded_array_class_get (eclass, rank, FALSE);
6832 * mono_class_instance_size:
6835 * Use to get the size of a class in bytes.
6837 * Returns: The size of an object instance
6840 mono_class_instance_size (MonoClass *klass)
6842 if (!klass->size_inited)
6843 mono_class_init (klass);
6845 return klass->instance_size;
6849 * mono_class_min_align:
6852 * Use to get the computed minimum alignment requirements for the specified class.
6854 * Returns: minimm alignment requirements
6857 mono_class_min_align (MonoClass *klass)
6859 if (!klass->size_inited)
6860 mono_class_init (klass);
6862 return klass->min_align;
6866 * mono_class_value_size:
6869 * This function is used for value types, and return the
6870 * space and the alignment to store that kind of value object.
6872 * Returns: the size of a value of kind @klass
6875 mono_class_value_size (MonoClass *klass, guint32 *align)
6879 /* fixme: check disable, because we still have external revereces to
6880 * mscorlib and Dummy Objects
6882 /*g_assert (klass->valuetype);*/
6884 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6887 *align = klass->min_align;
6893 * mono_class_data_size:
6896 * Returns: The size of the static class data
6899 mono_class_data_size (MonoClass *klass)
6902 mono_class_init (klass);
6903 /* This can happen with dynamically created types */
6904 if (!klass->fields_inited)
6905 mono_class_setup_fields_locking (klass);
6907 /* in arrays, sizes.class_size is unioned with element_size
6908 * and arrays have no static fields
6912 return klass->sizes.class_size;
6916 * Auxiliary routine to mono_class_get_field
6918 * Takes a field index instead of a field token.
6920 static MonoClassField *
6921 mono_class_get_field_idx (MonoClass *klass, int idx)
6923 mono_class_setup_fields_locking (klass);
6924 if (mono_class_has_failure (klass))
6928 if (klass->image->uncompressed_metadata) {
6930 * klass->field.first points to the FieldPtr table, while idx points into the
6931 * Field table, so we have to do a search.
6933 /*FIXME this is broken for types with multiple fields with the same name.*/
6934 const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6937 for (i = 0; i < klass->field.count; ++i)
6938 if (mono_field_get_name (&klass->fields [i]) == name)
6939 return &klass->fields [i];
6940 g_assert_not_reached ();
6942 if (klass->field.count) {
6943 if ((idx >= klass->field.first) && (idx < klass->field.first + klass->field.count)){
6944 return &klass->fields [idx - klass->field.first];
6948 klass = klass->parent;
6954 * mono_class_get_field:
6955 * @class: the class to lookup the field.
6956 * @field_token: the field token
6958 * Returns: A MonoClassField representing the type and offset of
6959 * the field, or a NULL value if the field does not belong to this
6963 mono_class_get_field (MonoClass *klass, guint32 field_token)
6965 int idx = mono_metadata_token_index (field_token);
6967 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6969 return mono_class_get_field_idx (klass, idx - 1);
6973 * mono_class_get_field_from_name:
6974 * @klass: the class to lookup the field.
6975 * @name: the field name
6977 * Search the class @klass and it's parents for a field with the name @name.
6979 * Returns: The MonoClassField pointer of the named field or NULL
6982 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6984 return mono_class_get_field_from_name_full (klass, name, NULL);
6988 * mono_class_get_field_from_name_full:
6989 * @klass: the class to lookup the field.
6990 * @name: the field name
6991 * @type: the type of the fields. This optional.
6993 * Search the class @klass and it's parents for a field with the name @name and type @type.
6995 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
6996 * of its generic type definition.
6998 * Returns: The MonoClassField pointer of the named field or NULL
7001 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
7005 mono_class_setup_fields_locking (klass);
7006 if (mono_class_has_failure (klass))
7010 for (i = 0; i < klass->field.count; ++i) {
7011 MonoClassField *field = &klass->fields [i];
7013 if (strcmp (name, mono_field_get_name (field)) != 0)
7017 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
7018 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
7023 klass = klass->parent;
7029 * mono_class_get_field_token:
7030 * @field: the field we need the token of
7032 * Get the token of a field. Note that the tokesn is only valid for the image
7033 * the field was loaded from. Don't use this function for fields in dynamic types.
7035 * Returns: The token representing the field in the image it was loaded from.
7038 mono_class_get_field_token (MonoClassField *field)
7040 MonoClass *klass = field->parent;
7043 mono_class_setup_fields_locking (klass);
7048 for (i = 0; i < klass->field.count; ++i) {
7049 if (&klass->fields [i] == field) {
7050 int idx = klass->field.first + i + 1;
7052 if (klass->image->uncompressed_metadata)
7053 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
7054 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
7057 klass = klass->parent;
7060 g_assert_not_reached ();
7065 mono_field_get_index (MonoClassField *field)
7067 int index = field - field->parent->fields;
7069 g_assert (index >= 0 && index < field->parent->field.count);
7075 * mono_class_get_field_default_value:
7077 * Return the default value of the field as a pointer into the metadata blob.
7080 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
7083 guint32 constant_cols [MONO_CONSTANT_SIZE];
7085 MonoClass *klass = field->parent;
7087 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7089 if (!klass->ext || !klass->ext->field_def_values) {
7090 MonoFieldDefaultValue *def_values;
7092 mono_class_alloc_ext (klass);
7094 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
7096 mono_image_lock (klass->image);
7097 mono_memory_barrier ();
7098 if (!klass->ext->field_def_values)
7099 klass->ext->field_def_values = def_values;
7100 mono_image_unlock (klass->image);
7103 field_index = mono_field_get_index (field);
7105 if (!klass->ext->field_def_values [field_index].data) {
7106 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7110 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7112 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7113 klass->ext->field_def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7114 klass->ext->field_def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7117 *def_type = klass->ext->field_def_values [field_index].def_type;
7118 return klass->ext->field_def_values [field_index].data;
7122 mono_property_get_index (MonoProperty *prop)
7124 int index = prop - prop->parent->ext->properties;
7126 g_assert (index >= 0 && index < prop->parent->ext->property.count);
7132 * mono_class_get_property_default_value:
7134 * Return the default value of the field as a pointer into the metadata blob.
7137 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7140 guint32 constant_cols [MONO_CONSTANT_SIZE];
7141 MonoClass *klass = property->parent;
7143 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7145 * We don't cache here because it is not used by C# so it's quite rare, but
7146 * we still do the lookup in klass->ext because that is where the data
7147 * is stored for dynamic assemblies.
7150 if (image_is_dynamic (klass->image)) {
7151 int prop_index = mono_property_get_index (property);
7152 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
7153 *def_type = klass->ext->prop_def_values [prop_index].def_type;
7154 return klass->ext->prop_def_values [prop_index].data;
7158 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7162 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7163 *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7164 return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7168 mono_class_get_event_token (MonoEvent *event)
7170 MonoClass *klass = event->parent;
7175 for (i = 0; i < klass->ext->event.count; ++i) {
7176 if (&klass->ext->events [i] == event)
7177 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
7180 klass = klass->parent;
7183 g_assert_not_reached ();
7188 * mono_class_get_property_from_name:
7190 * @name: name of the property to lookup in the specified class
7192 * Use this method to lookup a property in a class
7193 * Returns: the MonoProperty with the given name, or NULL if the property
7194 * does not exist on the @klass.
7197 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7201 gpointer iter = NULL;
7202 while ((p = mono_class_get_properties (klass, &iter))) {
7203 if (! strcmp (name, p->name))
7206 klass = klass->parent;
7212 * mono_class_get_property_token:
7213 * @prop: MonoProperty to query
7215 * Returns: The ECMA token for the specified property.
7218 mono_class_get_property_token (MonoProperty *prop)
7220 MonoClass *klass = prop->parent;
7224 gpointer iter = NULL;
7225 while ((p = mono_class_get_properties (klass, &iter))) {
7226 if (&klass->ext->properties [i] == prop)
7227 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
7231 klass = klass->parent;
7234 g_assert_not_reached ();
7239 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7241 const char *name, *nspace;
7242 if (image_is_dynamic (image))
7243 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7245 switch (type_token & 0xff000000){
7246 case MONO_TOKEN_TYPE_DEF: {
7247 guint32 cols [MONO_TYPEDEF_SIZE];
7248 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7249 guint tidx = mono_metadata_token_index (type_token);
7251 if (tidx > tt->rows)
7252 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7254 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7255 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7256 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7257 if (strlen (nspace) == 0)
7258 return g_strdup_printf ("%s", name);
7260 return g_strdup_printf ("%s.%s", nspace, name);
7263 case MONO_TOKEN_TYPE_REF: {
7265 guint32 cols [MONO_TYPEREF_SIZE];
7266 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7267 guint tidx = mono_metadata_token_index (type_token);
7270 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7272 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7273 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7274 mono_error_cleanup (&error);
7278 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7279 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7280 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7281 if (strlen (nspace) == 0)
7282 return g_strdup_printf ("%s", name);
7284 return g_strdup_printf ("%s.%s", nspace, name);
7287 case MONO_TOKEN_TYPE_SPEC:
7288 return g_strdup_printf ("Typespec 0x%08x", type_token);
7290 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7295 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7297 if (image_is_dynamic (image))
7298 return g_strdup_printf ("DynamicAssembly %s", image->name);
7300 switch (type_token & 0xff000000){
7301 case MONO_TOKEN_TYPE_DEF:
7302 if (image->assembly)
7303 return mono_stringify_assembly_name (&image->assembly->aname);
7304 else if (image->assembly_name)
7305 return g_strdup (image->assembly_name);
7306 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7307 case MONO_TOKEN_TYPE_REF: {
7309 MonoAssemblyName aname;
7310 guint32 cols [MONO_TYPEREF_SIZE];
7311 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7312 guint32 idx = mono_metadata_token_index (type_token);
7315 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7317 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7318 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7319 mono_error_cleanup (&error);
7322 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7324 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7325 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7326 case MONO_RESOLUTION_SCOPE_MODULE:
7328 return g_strdup ("");
7329 case MONO_RESOLUTION_SCOPE_MODULEREF:
7331 return g_strdup ("");
7332 case MONO_RESOLUTION_SCOPE_TYPEREF:
7334 return g_strdup ("");
7335 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7336 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7337 return mono_stringify_assembly_name (&aname);
7339 g_assert_not_reached ();
7343 case MONO_TOKEN_TYPE_SPEC:
7345 return g_strdup ("");
7347 g_assert_not_reached ();
7354 * mono_class_get_full:
7355 * @image: the image where the class resides
7356 * @type_token: the token for the class
7357 * @context: the generic context used to evaluate generic instantiations in
7358 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7360 * Returns: The MonoClass that represents @type_token in @image
7363 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7367 klass = mono_class_get_checked (image, type_token, &error);
7369 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7370 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7372 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7378 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7382 mono_error_init (error);
7383 klass = mono_class_get_checked (image, type_token, error);
7385 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7386 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7391 * mono_class_get_checked:
7392 * @image: the image where the class resides
7393 * @type_token: the token for the class
7394 * @error: error object to return any error
7396 * Returns: The MonoClass that represents @type_token in @image, or NULL on error.
7399 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7401 MonoClass *klass = NULL;
7403 mono_error_init (error);
7405 if (image_is_dynamic (image)) {
7406 int table = mono_metadata_token_table (type_token);
7408 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7409 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7412 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
7416 switch (type_token & 0xff000000){
7417 case MONO_TOKEN_TYPE_DEF:
7418 klass = mono_class_create_from_typedef (image, type_token, error);
7420 case MONO_TOKEN_TYPE_REF:
7421 klass = mono_class_from_typeref_checked (image, type_token, error);
7423 case MONO_TOKEN_TYPE_SPEC:
7424 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7427 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7431 /* Generic case, should be avoided for when a better error is possible. */
7432 if (!klass && mono_error_ok (error)) {
7433 char *name = mono_class_name_from_token (image, type_token);
7434 char *assembly = mono_assembly_name_from_token (image, type_token);
7435 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7443 * mono_type_get_checked:
7444 * @image: the image where the type resides
7445 * @type_token: the token for the type
7446 * @context: the generic context used to evaluate generic instantiations in
7447 * @error: Error handling context
7449 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7451 * Returns: The MonoType that represents @type_token in @image
7454 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7456 MonoType *type = NULL;
7457 gboolean inflated = FALSE;
7459 mono_error_init (error);
7461 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7462 if (image_is_dynamic (image)) {
7463 MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
7464 return_val_if_nok (error, NULL);
7465 return mono_class_get_type (klass);
7468 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7469 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7476 return mono_class_get_type (klass);
7479 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7486 MonoType *tmp = type;
7487 type = mono_class_get_type (mono_class_from_mono_type (type));
7488 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7489 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7490 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7492 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7494 if (type->type != tmp->type)
7497 mono_metadata_free_type (tmp);
7504 * @image: image where the class token will be looked up.
7505 * @type_token: a type token from the image
7507 * Returns the MonoClass with the given @type_token on the @image
7510 mono_class_get (MonoImage *image, guint32 type_token)
7512 return mono_class_get_full (image, type_token, NULL);
7516 * mono_image_init_name_cache:
7518 * Initializes the class name cache stored in image->name_cache.
7520 * LOCKING: Acquires the corresponding image lock.
7523 mono_image_init_name_cache (MonoImage *image)
7525 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7526 guint32 cols [MONO_TYPEDEF_SIZE];
7529 guint32 i, visib, nspace_index;
7530 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7532 if (image->name_cache)
7535 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7537 if (image_is_dynamic (image)) {
7538 mono_image_lock (image);
7539 if (image->name_cache) {
7540 /* Somebody initialized it before us */
7541 g_hash_table_destroy (the_name_cache);
7543 mono_atomic_store_release (&image->name_cache, the_name_cache);
7545 mono_image_unlock (image);
7549 /* Temporary hash table to avoid lookups in the nspace_table */
7550 name_cache2 = g_hash_table_new (NULL, NULL);
7552 for (i = 1; i <= t->rows; ++i) {
7553 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7554 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7556 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7557 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7559 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7561 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7562 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7564 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7565 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7566 if (!nspace_table) {
7567 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7568 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7569 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7572 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7575 /* Load type names from EXPORTEDTYPES table */
7577 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7578 guint32 cols [MONO_EXP_TYPE_SIZE];
7581 for (i = 0; i < t->rows; ++i) {
7582 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7584 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7585 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7589 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7590 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7592 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7593 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7594 if (!nspace_table) {
7595 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7596 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7597 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7600 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7604 g_hash_table_destroy (name_cache2);
7606 mono_image_lock (image);
7607 if (image->name_cache) {
7608 /* Somebody initialized it before us */
7609 g_hash_table_destroy (the_name_cache);
7611 mono_atomic_store_release (&image->name_cache, the_name_cache);
7613 mono_image_unlock (image);
7616 /*FIXME Only dynamic assemblies should allow this operation.*/
7618 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7619 const char *name, guint32 index)
7621 GHashTable *nspace_table;
7622 GHashTable *name_cache;
7625 mono_image_init_name_cache (image);
7626 mono_image_lock (image);
7628 name_cache = image->name_cache;
7629 if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7630 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7631 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7634 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7635 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7637 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7639 mono_image_unlock (image);
7648 find_nocase (gpointer key, gpointer value, gpointer user_data)
7650 char *name = (char*)key;
7651 FindUserData *data = (FindUserData*)user_data;
7653 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7654 data->value = value;
7658 * mono_class_from_name_case:
7659 * @image: The MonoImage where the type is looked up in
7660 * @name_space: the type namespace
7661 * @name: the type short name.
7662 * @deprecated: use the mono_class_from_name_case_checked variant instead.
7664 * Obtains a MonoClass with a given namespace and a given name which
7665 * is located in the given MonoImage. The namespace and name
7666 * lookups are case insensitive.
7669 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7672 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7673 mono_error_cleanup (&error);
7679 * mono_class_from_name_case:
7680 * @image: The MonoImage where the type is looked up in
7681 * @name_space: the type namespace
7682 * @name: the type short name.
7685 * Obtains a MonoClass with a given namespace and a given name which
7686 * is located in the given MonoImage. The namespace and name
7687 * lookups are case insensitive.
7689 * Returns: The MonoClass if the given namespace and name were found, or NULL if it
7690 * was not found. The @error object will contain information about the problem
7694 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7696 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7697 guint32 cols [MONO_TYPEDEF_SIZE];
7702 mono_error_init (error);
7704 if (image_is_dynamic (image)) {
7706 FindUserData user_data;
7708 mono_image_init_name_cache (image);
7709 mono_image_lock (image);
7711 user_data.key = name_space;
7712 user_data.value = NULL;
7713 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7715 if (user_data.value) {
7716 GHashTable *nspace_table = (GHashTable*)user_data.value;
7718 user_data.key = name;
7719 user_data.value = NULL;
7721 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7723 if (user_data.value)
7724 token = GPOINTER_TO_UINT (user_data.value);
7727 mono_image_unlock (image);
7730 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7736 /* add a cache if needed */
7737 for (i = 1; i <= t->rows; ++i) {
7738 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7739 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7741 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7742 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7744 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7746 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7747 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7748 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7749 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7755 return_nested_in (MonoClass *klass, char *nested)
7758 char *s = strchr (nested, '/');
7759 gpointer iter = NULL;
7766 while ((found = mono_class_get_nested_types (klass, &iter))) {
7767 if (strcmp (found->name, nested) == 0) {
7769 return return_nested_in (found, s);
7777 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7779 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7780 MonoImage *file_image;
7784 mono_error_init (error);
7787 * The EXPORTEDTYPES table only contains public types, so have to search the
7789 * Note: image->modules contains the contents of the MODULEREF table, while
7790 * the real module list is in the FILE table.
7792 for (i = 0; i < file_table->rows; i++) {
7793 guint32 cols [MONO_FILE_SIZE];
7794 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7795 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7798 file_image = mono_image_load_file_for_image_checked (image, i + 1, error);
7800 klass = mono_class_from_name_checked (file_image, name_space, name, error);
7801 if (klass || !is_ok (error))
7810 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7812 GHashTable *nspace_table;
7813 MonoImage *loaded_image;
7820 mono_error_init (error);
7822 // Checking visited images avoids stack overflows when cyclic references exist.
7823 if (g_hash_table_lookup (visited_images, image))
7826 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7828 if ((nested = strchr (name, '/'))) {
7829 int pos = nested - name;
7830 int len = strlen (name);
7833 memcpy (buf, name, len + 1);
7835 nested = buf + pos + 1;
7839 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7840 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7841 gboolean res = get_class_from_name (image, name_space, name, &klass);
7844 klass = search_modules (image, name_space, name, error);
7849 return klass ? return_nested_in (klass, nested) : NULL;
7855 mono_image_init_name_cache (image);
7856 mono_image_lock (image);
7858 nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7861 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7863 mono_image_unlock (image);
7865 if (!token && image_is_dynamic (image) && image->modules) {
7866 /* Search modules as well */
7867 for (i = 0; i < image->module_count; ++i) {
7868 MonoImage *module = image->modules [i];
7870 klass = mono_class_from_name_checked (module, name_space, name, error);
7871 if (klass || !is_ok (error))
7877 klass = search_modules (image, name_space, name, error);
7878 if (klass || !is_ok (error))
7883 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7884 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7885 guint32 cols [MONO_EXP_TYPE_SIZE];
7888 idx = mono_metadata_token_index (token);
7890 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7892 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7893 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7894 loaded_image = mono_assembly_load_module_checked (image->assembly, impl >> MONO_IMPLEMENTATION_BITS, error);
7897 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7899 return klass ? return_nested_in (klass, nested) : NULL;
7901 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7902 guint32 assembly_idx;
7904 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7906 mono_assembly_load_reference (image, assembly_idx - 1);
7907 g_assert (image->references [assembly_idx - 1]);
7908 if (image->references [assembly_idx - 1] == (gpointer)-1)
7910 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
7912 return klass ? return_nested_in (klass, nested) : NULL;
7915 g_assert_not_reached ();
7919 token = MONO_TOKEN_TYPE_DEF | token;
7921 klass = mono_class_get_checked (image, token, error);
7923 return return_nested_in (klass, nested);
7928 * mono_class_from_name_checked:
7929 * @image: The MonoImage where the type is looked up in
7930 * @name_space: the type namespace
7931 * @name: the type short name.
7933 * Obtains a MonoClass with a given namespace and a given name which
7934 * is located in the given MonoImage.
7936 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
7937 * set if the class was not found or it will return NULL and set the error if there was a loading error.
7940 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7943 GHashTable *visited_images;
7945 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7947 klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
7949 g_hash_table_destroy (visited_images);
7955 * mono_class_from_name:
7956 * @image: The MonoImage where the type is looked up in
7957 * @name_space: the type namespace
7958 * @name: the type short name.
7960 * Obtains a MonoClass with a given namespace and a given name which
7961 * is located in the given MonoImage.
7963 * To reference nested classes, use the "/" character as a separator.
7964 * For example use "Foo/Bar" to reference the class Bar that is nested
7965 * inside Foo, like this: "class Foo { class Bar {} }".
7968 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7973 klass = mono_class_from_name_checked (image, name_space, name, &error);
7974 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
7980 * mono_class_load_from_name:
7981 * @image: The MonoImage where the type is looked up in
7982 * @name_space: the type namespace
7983 * @name: the type short name.
7985 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
7986 * This function should be used by the runtime for critical types to which there's no way to recover but crash
7987 * If they are missing. Thing of System.Object or System.String.
7990 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
7995 klass = mono_class_from_name_checked (image, name_space, name, &error);
7997 g_error ("Runtime critical type %s.%s not found", name_space, name);
7998 if (!mono_error_ok (&error))
7999 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8004 * mono_class_try_load_from_name:
8005 * @image: The MonoImage where the type is looked up in
8006 * @name_space: the type namespace
8007 * @name: the type short name.
8009 * This function tries to load a type, returning the class was found or NULL otherwise.
8010 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
8012 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
8013 * a type that we would otherwise assume to be available but was not due some error.
8017 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
8022 klass = mono_class_from_name_checked (image, name_space, name, &error);
8023 if (!mono_error_ok (&error))
8024 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8030 * mono_class_is_subclass_of:
8031 * @klass: class to probe if it is a subclass of another one
8032 * @klassc: the class we suspect is the base class
8033 * @check_interfaces: whether we should perform interface checks
8035 * This method determines whether @klass is a subclass of @klassc.
8037 * If the @check_interfaces flag is set, then if @klassc is an interface
8038 * this method return TRUE if the @klass implements the interface or
8039 * if @klass is an interface, if one of its base classes is @klass.
8041 * If @check_interfaces is false then, then if @klass is not an interface
8042 * then it returns TRUE if the @klass is a subclass of @klassc.
8044 * if @klass is an interface and @klassc is System.Object, then this function
8049 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
8050 gboolean check_interfaces)
8052 /* FIXME test for interfaces with variant generic arguments */
8053 mono_class_init (klass);
8054 mono_class_init (klassc);
8056 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
8057 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
8059 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
8062 for (i = 0; i < klass->interface_count; i ++) {
8063 MonoClass *ic = klass->interfaces [i];
8068 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
8073 * MS.NET thinks interfaces are a subclass of Object, so we think it as
8076 if (klassc == mono_defaults.object_class)
8083 mono_type_is_generic_argument (MonoType *type)
8085 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
8089 mono_class_has_variant_generic_params (MonoClass *klass)
8092 MonoGenericContainer *container;
8094 if (!klass->generic_class)
8097 container = klass->generic_class->container_class->generic_container;
8099 for (i = 0; i < container->type_argc; ++i)
8100 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8107 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8109 if (target == candidate)
8112 if (check_for_reference_conv &&
8113 mono_type_is_generic_argument (&target->byval_arg) &&
8114 mono_type_is_generic_argument (&candidate->byval_arg)) {
8115 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8116 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8118 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8121 if (!mono_class_is_assignable_from (target, candidate))
8127 * @container the generic container from the GTD
8128 * @klass: the class to be assigned to
8129 * @oklass: the source class
8131 * Both @klass and @oklass must be instances of the same generic interface.
8133 * Returns: TRUE if @klass can be assigned to a @klass variable
8136 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8139 MonoType **klass_argv, **oklass_argv;
8140 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8141 MonoGenericContainer *container = klass_gtd->generic_container;
8143 if (klass == oklass)
8146 /*Viable candidates are instances of the same generic interface*/
8147 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8150 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8151 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8153 for (j = 0; j < container->type_argc; ++j) {
8154 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8155 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8157 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8161 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8162 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8164 if (param1_class != param2_class) {
8165 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8166 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8168 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8169 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8179 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8181 MonoGenericParam *gparam, *ogparam;
8182 MonoGenericParamInfo *tinfo, *cinfo;
8183 MonoClass **candidate_class;
8184 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8187 if (target == candidate)
8189 if (target->byval_arg.type != candidate->byval_arg.type)
8192 gparam = target->byval_arg.data.generic_param;
8193 ogparam = candidate->byval_arg.data.generic_param;
8194 tinfo = mono_generic_param_info (gparam);
8195 cinfo = mono_generic_param_info (ogparam);
8197 class_constraint_satisfied = FALSE;
8198 valuetype_constraint_satisfied = FALSE;
8200 /*candidate must have a super set of target's special constraints*/
8201 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8202 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8204 if (cinfo->constraints) {
8205 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8206 MonoClass *cc = *candidate_class;
8208 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8209 class_constraint_satisfied = TRUE;
8210 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8211 valuetype_constraint_satisfied = TRUE;
8214 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8215 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8217 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8219 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8221 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8222 valuetype_constraint_satisfied)) {
8227 /*candidate type constraints must be a superset of target's*/
8228 if (tinfo->constraints) {
8229 MonoClass **target_class;
8230 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8231 MonoClass *tc = *target_class;
8234 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8235 * check it's constraints since it satisfy the constraint by itself.
8237 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8240 if (!cinfo->constraints)
8243 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8244 MonoClass *cc = *candidate_class;
8246 if (mono_class_is_assignable_from (tc, cc))
8250 * This happens when we have the following:
8252 * Bar<K> where K : IFace
8253 * Foo<T, U> where T : U where U : IFace
8255 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8258 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8259 if (mono_gparam_is_assignable_from (target, cc))
8263 if (!*candidate_class)
8268 /*candidate itself must have a constraint that satisfy target*/
8269 if (cinfo->constraints) {
8270 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8271 MonoClass *cc = *candidate_class;
8272 if (mono_class_is_assignable_from (target, cc))
8280 * mono_class_is_assignable_from:
8281 * @klass: the class to be assigned to
8282 * @oklass: the source class
8284 * Returns: TRUE if an instance of object oklass can be assigned to an
8285 * instance of object @klass
8288 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8291 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8293 mono_class_init (klass);
8295 if (!oklass->inited)
8296 mono_class_init (oklass);
8298 if (mono_class_has_failure (klass) || mono_class_has_failure (oklass))
8301 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8302 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8304 return mono_gparam_is_assignable_from (klass, oklass);
8307 if (MONO_CLASS_IS_INTERFACE (klass)) {
8308 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8309 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8310 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8314 for (i = 0; constraints [i]; ++i) {
8315 if (mono_class_is_assignable_from (klass, constraints [i]))
8323 /* interface_offsets might not be set for dynamic classes */
8324 if (oklass->ref_info_handle && !oklass->interface_bitmap) {
8326 * oklass might be a generic type parameter but they have
8327 * interface_offsets set.
8329 gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8330 if (!is_ok (&error)) {
8331 mono_error_cleanup (&error);
8336 if (!oklass->interface_bitmap)
8337 /* Happens with generic instances of not-yet created dynamic types */
8339 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8342 if (mono_class_has_variant_generic_params (klass)) {
8344 mono_class_setup_interfaces (oklass, &error);
8345 if (!mono_error_ok (&error)) {
8346 mono_error_cleanup (&error);
8350 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8351 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8352 MonoClass *iface = oklass->interfaces_packed [i];
8354 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8359 } else if (klass->delegate) {
8360 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8362 }else if (klass->rank) {
8363 MonoClass *eclass, *eoclass;
8365 if (oklass->rank != klass->rank)
8368 /* vectors vs. one dimensional arrays */
8369 if (oklass->byval_arg.type != klass->byval_arg.type)
8372 eclass = klass->cast_class;
8373 eoclass = oklass->cast_class;
8376 * a is b does not imply a[] is b[] when a is a valuetype, and
8377 * b is a reference type.
8380 if (eoclass->valuetype) {
8381 if ((eclass == mono_defaults.enum_class) ||
8382 (eclass == mono_defaults.enum_class->parent) ||
8383 (eclass == mono_defaults.object_class))
8387 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8388 } else if (mono_class_is_nullable (klass)) {
8389 if (mono_class_is_nullable (oklass))
8390 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8392 return mono_class_is_assignable_from (klass->cast_class, oklass);
8393 } else if (klass == mono_defaults.object_class)
8396 return mono_class_has_parent (oklass, klass);
8399 /*Check if @oklass is variant compatible with @klass.*/
8401 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8404 MonoType **klass_argv, **oklass_argv;
8405 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8406 MonoGenericContainer *container = klass_gtd->generic_container;
8408 /*Viable candidates are instances of the same generic interface*/
8409 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8412 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8413 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8415 for (j = 0; j < container->type_argc; ++j) {
8416 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8417 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8419 if (param1_class->valuetype != param2_class->valuetype)
8423 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8424 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8426 if (param1_class != param2_class) {
8427 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8428 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8430 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8431 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8439 /*Check if @candidate implements the interface @target*/
8441 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8445 gboolean is_variant = mono_class_has_variant_generic_params (target);
8447 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8448 if (mono_class_is_variant_compatible_slow (target, candidate))
8453 if (candidate == target)
8456 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8457 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8458 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (candidate);
8460 if (tb && tb->interfaces) {
8461 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8462 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8463 MonoClass *iface_class;
8465 /* we can't realize the type here since it can do pretty much anything. */
8468 iface_class = mono_class_from_mono_type (iface->type);
8469 if (iface_class == target)
8471 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8473 if (mono_class_implement_interface_slow (target, iface_class))
8478 /*setup_interfaces don't mono_class_init anything*/
8479 /*FIXME this doesn't handle primitive type arrays.
8480 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8481 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8483 mono_class_setup_interfaces (candidate, &error);
8484 if (!mono_error_ok (&error)) {
8485 mono_error_cleanup (&error);
8489 for (i = 0; i < candidate->interface_count; ++i) {
8490 if (candidate->interfaces [i] == target)
8493 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8496 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8500 candidate = candidate->parent;
8501 } while (candidate);
8507 * Check if @oklass can be assigned to @klass.
8508 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8511 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8513 if (candidate == target)
8515 if (target == mono_defaults.object_class)
8518 if (mono_class_has_parent (candidate, target))
8521 /*If target is not an interface there is no need to check them.*/
8522 if (MONO_CLASS_IS_INTERFACE (target))
8523 return mono_class_implement_interface_slow (target, candidate);
8525 if (target->delegate && mono_class_has_variant_generic_params (target))
8526 return mono_class_is_variant_compatible (target, candidate, FALSE);
8529 MonoClass *eclass, *eoclass;
8531 if (target->rank != candidate->rank)
8534 /* vectors vs. one dimensional arrays */
8535 if (target->byval_arg.type != candidate->byval_arg.type)
8538 eclass = target->cast_class;
8539 eoclass = candidate->cast_class;
8542 * a is b does not imply a[] is b[] when a is a valuetype, and
8543 * b is a reference type.
8546 if (eoclass->valuetype) {
8547 if ((eclass == mono_defaults.enum_class) ||
8548 (eclass == mono_defaults.enum_class->parent) ||
8549 (eclass == mono_defaults.object_class))
8553 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8555 /*FIXME properly handle nullables */
8556 /*FIXME properly handle (M)VAR */
8561 * mono_class_get_cctor:
8562 * @klass: A MonoClass pointer
8564 * Returns: The static constructor of @klass if it exists, NULL otherwise.
8567 mono_class_get_cctor (MonoClass *klass)
8569 MonoCachedClassInfo cached_info;
8571 if (image_is_dynamic (klass->image)) {
8573 * has_cctor is not set for these classes because mono_class_init () is
8576 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8579 if (!klass->has_cctor)
8582 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8584 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8585 if (!mono_error_ok (&error))
8586 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8590 if (klass->generic_class && !klass->methods)
8591 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8593 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8597 * mono_class_get_finalizer:
8598 * @klass: The MonoClass pointer
8600 * Returns: The finalizer method of @klass if it exists, NULL otherwise.
8603 mono_class_get_finalizer (MonoClass *klass)
8605 MonoCachedClassInfo cached_info;
8608 mono_class_init (klass);
8609 if (!mono_class_has_finalizer (klass))
8612 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8614 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8615 if (!mono_error_ok (&error))
8616 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8619 mono_class_setup_vtable (klass);
8620 return klass->vtable [finalize_slot];
8625 * mono_class_needs_cctor_run:
8626 * @klass: the MonoClass pointer
8627 * @caller: a MonoMethod describing the caller
8629 * Determines whenever the class has a static constructor and whenever it
8630 * needs to be called when executing CALLER.
8633 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8637 method = mono_class_get_cctor (klass);
8639 return (method == caller) ? FALSE : TRUE;
8645 * mono_class_array_element_size:
8648 * Returns: The number of bytes an element of type @klass
8649 * uses when stored into an array.
8652 mono_class_array_element_size (MonoClass *klass)
8654 MonoType *type = &klass->byval_arg;
8657 switch (type->type) {
8660 case MONO_TYPE_BOOLEAN:
8664 case MONO_TYPE_CHAR:
8673 case MONO_TYPE_CLASS:
8674 case MONO_TYPE_STRING:
8675 case MONO_TYPE_OBJECT:
8676 case MONO_TYPE_SZARRAY:
8677 case MONO_TYPE_ARRAY:
8678 return sizeof (gpointer);
8683 case MONO_TYPE_VALUETYPE:
8684 if (type->data.klass->enumtype) {
8685 type = mono_class_enum_basetype (type->data.klass);
8686 klass = klass->element_class;
8689 return mono_class_instance_size (klass) - sizeof (MonoObject);
8690 case MONO_TYPE_GENERICINST:
8691 type = &type->data.generic_class->container_class->byval_arg;
8694 case MONO_TYPE_MVAR: {
8697 return mono_type_size (type, &align);
8699 case MONO_TYPE_VOID:
8703 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8709 * mono_array_element_size:
8710 * @ac: pointer to a #MonoArrayClass
8712 * Returns: The size of single array element.
8715 mono_array_element_size (MonoClass *ac)
8717 g_assert (ac->rank);
8718 return ac->sizes.element_size;
8722 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8723 MonoGenericContext *context)
8726 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8727 g_assert (mono_error_ok (&error));
8732 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8733 MonoGenericContext *context, MonoError *error)
8735 mono_error_init (error);
8737 if (image_is_dynamic (image)) {
8738 MonoClass *tmp_handle_class;
8739 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
8741 mono_error_assert_ok (error);
8742 g_assert (tmp_handle_class);
8744 *handle_class = tmp_handle_class;
8746 if (tmp_handle_class == mono_defaults.typehandle_class)
8747 return &((MonoClass*)obj)->byval_arg;
8752 switch (token & 0xff000000) {
8753 case MONO_TOKEN_TYPE_DEF:
8754 case MONO_TOKEN_TYPE_REF:
8755 case MONO_TOKEN_TYPE_SPEC: {
8758 *handle_class = mono_defaults.typehandle_class;
8759 type = mono_type_get_checked (image, token, context, error);
8763 mono_class_init (mono_class_from_mono_type (type));
8764 /* We return a MonoType* as handle */
8767 case MONO_TOKEN_FIELD_DEF: {
8769 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8771 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8775 *handle_class = mono_defaults.fieldhandle_class;
8776 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8780 mono_class_init (klass);
8781 return mono_class_get_field (klass, token);
8783 case MONO_TOKEN_METHOD_DEF:
8784 case MONO_TOKEN_METHOD_SPEC: {
8786 meth = mono_get_method_checked (image, token, NULL, context, error);
8788 *handle_class = mono_defaults.methodhandle_class;
8794 case MONO_TOKEN_MEMBER_REF: {
8795 guint32 cols [MONO_MEMBERREF_SIZE];
8797 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8798 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8799 mono_metadata_decode_blob_size (sig, &sig);
8800 if (*sig == 0x6) { /* it's a field */
8802 MonoClassField *field;
8803 field = mono_field_from_token_checked (image, token, &klass, context, error);
8805 *handle_class = mono_defaults.fieldhandle_class;
8809 meth = mono_get_method_checked (image, token, NULL, context, error);
8811 *handle_class = mono_defaults.methodhandle_class;
8816 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8822 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
8824 MonoClass *handle_class;
8825 mono_error_init (error);
8826 return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
8830 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
8832 return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
8835 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8838 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8840 get_cached_class_info = func;
8844 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8846 if (!get_cached_class_info)
8849 return get_cached_class_info (klass, res);
8853 mono_install_get_class_from_name (MonoGetClassFromName func)
8855 get_class_from_name = func;
8859 * mono_class_get_image:
8861 * Use this method to get the `MonoImage*` where this class came from.
8863 * Returns: The image where this class is defined.
8866 mono_class_get_image (MonoClass *klass)
8868 return klass->image;
8872 * mono_class_get_element_class:
8873 * @klass: the MonoClass to act on
8875 * Use this function to get the element class of an array.
8877 * Returns: The element class of an array.
8880 mono_class_get_element_class (MonoClass *klass)
8882 return klass->element_class;
8886 * mono_class_is_valuetype:
8887 * @klass: the MonoClass to act on
8889 * Use this method to determine if the provided `MonoClass*` represents a value type,
8890 * or a reference type.
8892 * Returns: TRUE if the MonoClass represents a ValueType, FALSE if it represents a reference type.
8895 mono_class_is_valuetype (MonoClass *klass)
8897 return klass->valuetype;
8901 * mono_class_is_enum:
8902 * @klass: the MonoClass to act on
8904 * Use this function to determine if the provided `MonoClass*` represents an enumeration.
8906 * Returns: TRUE if the MonoClass represents an enumeration.
8909 mono_class_is_enum (MonoClass *klass)
8911 return klass->enumtype;
8915 * mono_class_enum_basetype:
8916 * @klass: the MonoClass to act on
8918 * Use this function to get the underlying type for an enumeration value.
8920 * Returns: The underlying type representation for an enumeration.
8923 mono_class_enum_basetype (MonoClass *klass)
8925 if (klass->element_class == klass)
8926 /* SRE or broken types */
8929 return &klass->element_class->byval_arg;
8933 * mono_class_get_parent
8934 * @klass: the MonoClass to act on
8936 * Returns: The parent class for this class.
8939 mono_class_get_parent (MonoClass *klass)
8941 return klass->parent;
8945 * mono_class_get_nesting_type:
8946 * @klass: the MonoClass to act on
8948 * Use this function to obtain the class that the provided `MonoClass*` is nested on.
8950 * If the return is NULL, this indicates that this class is not nested.
8952 * Returns: The container type where this type is nested or NULL if this type is not a nested type.
8955 mono_class_get_nesting_type (MonoClass *klass)
8957 return klass->nested_in;
8961 * mono_class_get_rank:
8962 * @klass: the MonoClass to act on
8964 * Returns: The rank for the array (the number of dimensions).
8967 mono_class_get_rank (MonoClass *klass)
8973 * mono_class_get_flags:
8974 * @klass: the MonoClass to act on
8976 * The type flags from the TypeDef table from the metadata.
8977 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8980 * Returns: The flags from the TypeDef table.
8983 mono_class_get_flags (MonoClass *klass)
8985 return klass->flags;
8989 * mono_class_get_name
8990 * @klass: the MonoClass to act on
8992 * Returns: The name of the class.
8995 mono_class_get_name (MonoClass *klass)
9001 * mono_class_get_namespace:
9002 * @klass: the MonoClass to act on
9004 * Returns: The namespace of the class.
9007 mono_class_get_namespace (MonoClass *klass)
9009 return klass->name_space;
9013 * mono_class_get_type:
9014 * @klass: the MonoClass to act on
9016 * This method returns the internal Type representation for the class.
9018 * Returns: The MonoType from the class.
9021 mono_class_get_type (MonoClass *klass)
9023 return &klass->byval_arg;
9027 * mono_class_get_type_token:
9028 * @klass: the MonoClass to act on
9030 * This method returns type token for the class.
9032 * Returns: The type token for the class.
9035 mono_class_get_type_token (MonoClass *klass)
9037 return klass->type_token;
9041 * mono_class_get_byref_type:
9042 * @klass: the MonoClass to act on
9047 mono_class_get_byref_type (MonoClass *klass)
9049 return &klass->this_arg;
9053 * mono_class_num_fields:
9054 * @klass: the MonoClass to act on
9056 * Returns: The number of static and instance fields in the class.
9059 mono_class_num_fields (MonoClass *klass)
9061 return klass->field.count;
9065 * mono_class_num_methods:
9066 * @klass: the MonoClass to act on
9068 * Returns: The number of methods in the class.
9071 mono_class_num_methods (MonoClass *klass)
9073 return klass->method.count;
9077 * mono_class_num_properties
9078 * @klass: the MonoClass to act on
9080 * Returns: The number of properties in the class.
9083 mono_class_num_properties (MonoClass *klass)
9085 mono_class_setup_properties (klass);
9087 return klass->ext->property.count;
9091 * mono_class_num_events:
9092 * @klass: the MonoClass to act on
9094 * Returns: The number of events in the class.
9097 mono_class_num_events (MonoClass *klass)
9099 mono_class_setup_events (klass);
9101 return klass->ext->event.count;
9105 * mono_class_get_fields:
9106 * @klass: the MonoClass to act on
9108 * This routine is an iterator routine for retrieving the fields in a class.
9110 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9111 * iterate over all of the elements. When no more values are
9112 * available, the return value is NULL.
9114 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
9117 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9119 MonoClassField* field;
9123 mono_class_setup_fields_locking (klass);
9124 if (mono_class_has_failure (klass))
9126 /* start from the first */
9127 if (klass->field.count) {
9128 *iter = &klass->fields [0];
9129 return &klass->fields [0];
9135 field = (MonoClassField *)*iter;
9137 if (field < &klass->fields [klass->field.count]) {
9145 * mono_class_get_methods
9146 * @klass: the MonoClass to act on
9148 * This routine is an iterator routine for retrieving the fields in a class.
9150 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9151 * iterate over all of the elements. When no more values are
9152 * available, the return value is NULL.
9154 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
9157 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9159 MonoMethod** method;
9163 mono_class_setup_methods (klass);
9166 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9167 * FIXME we should better report this error to the caller
9169 if (!klass->methods)
9171 /* start from the first */
9172 if (klass->method.count) {
9173 *iter = &klass->methods [0];
9174 return klass->methods [0];
9180 method = (MonoMethod **)*iter;
9182 if (method < &klass->methods [klass->method.count]) {
9190 * mono_class_get_virtual_methods:
9192 * Iterate over the virtual methods of KLASS.
9194 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9197 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9199 MonoMethod** method;
9202 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9204 mono_class_setup_methods (klass);
9206 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9207 * FIXME we should better report this error to the caller
9209 if (!klass->methods)
9211 /* start from the first */
9212 method = &klass->methods [0];
9214 method = (MonoMethod **)*iter;
9217 while (method < &klass->methods [klass->method.count]) {
9218 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9222 if (method < &klass->methods [klass->method.count]) {
9229 /* Search directly in metadata to avoid calling setup_methods () */
9230 MonoMethod *res = NULL;
9236 start_index = GPOINTER_TO_UINT (*iter);
9239 for (i = start_index; i < klass->method.count; ++i) {
9242 /* klass->method.first points into the methodptr table */
9243 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
9245 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9249 if (i < klass->method.count) {
9251 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9252 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9254 /* Add 1 here so the if (*iter) check fails */
9255 *iter = GUINT_TO_POINTER (i + 1);
9264 * mono_class_get_properties:
9265 * @klass: the MonoClass to act on
9267 * This routine is an iterator routine for retrieving the properties in a class.
9269 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9270 * iterate over all of the elements. When no more values are
9271 * available, the return value is NULL.
9273 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9276 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9278 MonoProperty* property;
9282 mono_class_setup_properties (klass);
9283 /* start from the first */
9284 if (klass->ext->property.count) {
9285 *iter = &klass->ext->properties [0];
9286 return (MonoProperty *)*iter;
9292 property = (MonoProperty *)*iter;
9294 if (property < &klass->ext->properties [klass->ext->property.count]) {
9296 return (MonoProperty *)*iter;
9302 * mono_class_get_events:
9303 * @klass: the MonoClass to act on
9305 * This routine is an iterator routine for retrieving the properties in a class.
9307 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9308 * iterate over all of the elements. When no more values are
9309 * available, the return value is NULL.
9311 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9314 mono_class_get_events (MonoClass* klass, gpointer *iter)
9320 mono_class_setup_events (klass);
9321 /* start from the first */
9322 if (klass->ext->event.count) {
9323 *iter = &klass->ext->events [0];
9324 return (MonoEvent *)*iter;
9330 event = (MonoEvent *)*iter;
9332 if (event < &klass->ext->events [klass->ext->event.count]) {
9334 return (MonoEvent *)*iter;
9340 * mono_class_get_interfaces
9341 * @klass: the MonoClass to act on
9343 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9345 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9346 * iterate over all of the elements. When no more values are
9347 * available, the return value is NULL.
9349 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9352 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9360 mono_class_init (klass);
9361 if (!klass->interfaces_inited) {
9362 mono_class_setup_interfaces (klass, &error);
9363 if (!mono_error_ok (&error)) {
9364 mono_error_cleanup (&error);
9368 /* start from the first */
9369 if (klass->interface_count) {
9370 *iter = &klass->interfaces [0];
9371 return klass->interfaces [0];
9377 iface = (MonoClass **)*iter;
9379 if (iface < &klass->interfaces [klass->interface_count]) {
9387 setup_nested_types (MonoClass *klass)
9390 GList *classes, *nested_classes, *l;
9393 if (klass->nested_classes_inited)
9396 if (!klass->type_token)
9397 klass->nested_classes_inited = TRUE;
9399 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9403 guint32 cols [MONO_NESTED_CLASS_SIZE];
9404 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9405 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9406 if (!mono_error_ok (&error)) {
9407 /*FIXME don't swallow the error message*/
9408 mono_error_cleanup (&error);
9410 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9414 classes = g_list_prepend (classes, nclass);
9416 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9419 mono_class_alloc_ext (klass);
9421 nested_classes = NULL;
9422 for (l = classes; l; l = l->next)
9423 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9424 g_list_free (classes);
9426 mono_image_lock (klass->image);
9428 mono_memory_barrier ();
9429 if (!klass->nested_classes_inited) {
9430 klass->ext->nested_classes = nested_classes;
9431 mono_memory_barrier ();
9432 klass->nested_classes_inited = TRUE;
9435 mono_image_unlock (klass->image);
9439 * mono_class_get_nested_types
9440 * @klass: the MonoClass to act on
9442 * This routine is an iterator routine for retrieving the nested types of a class.
9443 * This works only if @klass is non-generic, or a generic type definition.
9445 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9446 * iterate over all of the elements. When no more values are
9447 * available, the return value is NULL.
9449 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9452 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9458 if (!klass->nested_classes_inited)
9459 setup_nested_types (klass);
9462 /* start from the first */
9463 if (klass->ext && klass->ext->nested_classes) {
9464 *iter = klass->ext->nested_classes;
9465 return (MonoClass *)klass->ext->nested_classes->data;
9467 /* no nested types */
9471 item = (GList *)*iter;
9475 return (MonoClass *)item->data;
9482 * mono_class_is_delegate
9483 * @klass: the MonoClass to act on
9485 * Returns: TRUE if the MonoClass represents a System.Delegate.
9488 mono_class_is_delegate (MonoClass *klass)
9490 return klass->delegate;
9494 * mono_class_implements_interface
9495 * @klass: The MonoClass to act on
9496 * @interface: The interface to check if @klass implements.
9498 * Returns: TRUE if @klass implements @interface.
9501 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9503 return mono_class_is_assignable_from (iface, klass);
9507 * mono_field_get_name:
9508 * @field: the MonoClassField to act on
9510 * Returns: The name of the field.
9513 mono_field_get_name (MonoClassField *field)
9519 * mono_field_get_type:
9520 * @field: the MonoClassField to act on
9522 * Returns: MonoType of the field.
9525 mono_field_get_type (MonoClassField *field)
9528 MonoType *type = mono_field_get_type_checked (field, &error);
9529 if (!mono_error_ok (&error)) {
9530 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9531 mono_error_cleanup (&error);
9538 * mono_field_get_type_checked:
9539 * @field: the MonoClassField to act on
9540 * @error: used to return any erro found while retrieving @field type
9542 * Returns: MonoType of the field.
9545 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9547 mono_error_init (error);
9549 mono_field_resolve_type (field, error);
9554 * mono_field_get_parent:
9555 * @field: the MonoClassField to act on
9557 * Returns: MonoClass where the field was defined.
9560 mono_field_get_parent (MonoClassField *field)
9562 return field->parent;
9566 * mono_field_get_flags;
9567 * @field: the MonoClassField to act on
9569 * The metadata flags for a field are encoded using the
9570 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9572 * Returns: The flags for the field.
9575 mono_field_get_flags (MonoClassField *field)
9578 return mono_field_resolve_flags (field);
9579 return field->type->attrs;
9583 * mono_field_get_offset:
9584 * @field: the MonoClassField to act on
9586 * Returns: The field offset.
9589 mono_field_get_offset (MonoClassField *field)
9591 return field->offset;
9595 mono_field_get_rva (MonoClassField *field)
9599 MonoClass *klass = field->parent;
9600 MonoFieldDefaultValue *field_def_values;
9602 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9604 if (!klass->ext || !klass->ext->field_def_values) {
9605 mono_class_alloc_ext (klass);
9607 field_def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9609 mono_image_lock (klass->image);
9610 if (!klass->ext->field_def_values)
9611 klass->ext->field_def_values = field_def_values;
9612 mono_image_unlock (klass->image);
9615 field_index = mono_field_get_index (field);
9617 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9618 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9620 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9621 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9624 return klass->ext->field_def_values [field_index].data;
9628 * mono_field_get_data:
9629 * @field: the MonoClassField to act on
9631 * Returns: A pointer to the metadata constant value or to the field
9632 * data if it has an RVA flag.
9635 mono_field_get_data (MonoClassField *field)
9637 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9638 MonoTypeEnum def_type;
9640 return mono_class_get_field_default_value (field, &def_type);
9641 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9642 return mono_field_get_rva (field);
9649 * mono_property_get_name:
9650 * @prop: the MonoProperty to act on
9652 * Returns: The name of the property
9655 mono_property_get_name (MonoProperty *prop)
9661 * mono_property_get_set_method
9662 * @prop: the MonoProperty to act on.
9664 * Returns: The setter method of the property (A MonoMethod)
9667 mono_property_get_set_method (MonoProperty *prop)
9673 * mono_property_get_get_method
9674 * @prop: the MonoProperty to act on.
9676 * Returns: The setter method of the property (A MonoMethod)
9679 mono_property_get_get_method (MonoProperty *prop)
9685 * mono_property_get_parent:
9686 * @prop: the MonoProperty to act on.
9688 * Returns: The MonoClass where the property was defined.
9691 mono_property_get_parent (MonoProperty *prop)
9693 return prop->parent;
9697 * mono_property_get_flags:
9698 * @prop: the MonoProperty to act on.
9700 * The metadata flags for a property are encoded using the
9701 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9703 * Returns: The flags for the property.
9706 mono_property_get_flags (MonoProperty *prop)
9712 * mono_event_get_name:
9713 * @event: the MonoEvent to act on
9715 * Returns: The name of the event.
9718 mono_event_get_name (MonoEvent *event)
9724 * mono_event_get_add_method:
9725 * @event: The MonoEvent to act on.
9727 * Returns: The @add' method for the event (a MonoMethod).
9730 mono_event_get_add_method (MonoEvent *event)
9736 * mono_event_get_remove_method:
9737 * @event: The MonoEvent to act on.
9739 * Returns: The @remove method for the event (a MonoMethod).
9742 mono_event_get_remove_method (MonoEvent *event)
9744 return event->remove;
9748 * mono_event_get_raise_method:
9749 * @event: The MonoEvent to act on.
9751 * Returns: The @raise method for the event (a MonoMethod).
9754 mono_event_get_raise_method (MonoEvent *event)
9756 return event->raise;
9760 * mono_event_get_parent:
9761 * @event: the MonoEvent to act on.
9763 * Returns: The MonoClass where the event is defined.
9766 mono_event_get_parent (MonoEvent *event)
9768 return event->parent;
9772 * mono_event_get_flags
9773 * @event: the MonoEvent to act on.
9775 * The metadata flags for an event are encoded using the
9776 * EVENT_* constants. See the tabledefs.h file for details.
9778 * Returns: The flags for the event.
9781 mono_event_get_flags (MonoEvent *event)
9783 return event->attrs;
9787 * mono_class_get_method_from_name:
9788 * @klass: where to look for the method
9789 * @name: name of the method
9790 * @param_count: number of parameters. -1 for any number.
9792 * Obtains a MonoMethod with a given name and number of parameters.
9793 * It only works if there are no multiple signatures for any given method name.
9796 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9798 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9802 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9804 MonoMethod *res = NULL;
9807 /* Search directly in the metadata to avoid calling setup_methods () */
9808 for (i = 0; i < klass->method.count; ++i) {
9810 guint32 cols [MONO_METHOD_SIZE];
9812 MonoMethodSignature *sig;
9814 /* klass->method.first points into the methodptr table */
9815 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9817 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9818 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9820 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9823 if (param_count == -1) {
9827 sig = mono_method_signature_checked (method, &error);
9829 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9832 if (sig->param_count == param_count) {
9843 * mono_class_get_method_from_name_flags:
9844 * @klass: where to look for the method
9845 * @name_space: name of the method
9846 * @param_count: number of parameters. -1 for any number.
9847 * @flags: flags which must be set in the method
9849 * Obtains a MonoMethod with a given name and number of parameters.
9850 * It only works if there are no multiple signatures for any given method name.
9853 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9855 MonoMethod *res = NULL;
9858 mono_class_init (klass);
9860 if (klass->generic_class && !klass->methods) {
9861 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9864 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9865 if (!mono_error_ok (&error))
9866 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9871 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9872 mono_class_setup_methods (klass);
9874 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9875 See mono/tests/array_load_exception.il
9876 FIXME we should better report this error to the caller
9878 if (!klass->methods)
9880 for (i = 0; i < klass->method.count; ++i) {
9881 MonoMethod *method = klass->methods [i];
9883 if (method->name[0] == name [0] &&
9884 !strcmp (name, method->name) &&
9885 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9886 ((method->flags & flags) == flags)) {
9893 res = find_method_in_metadata (klass, name, param_count, flags);
9900 * mono_class_set_failure:
9901 * @klass: class in which the failure was detected
9902 * @ex_type: the kind of exception/error to be thrown (later)
9903 * @ex_data: exception data (specific to each type of exception/error)
9905 * Keep a detected failure informations in the class for later processing.
9906 * Note that only the first failure is kept.
9908 * LOCKING: Acquires the loader lock.
9911 mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error)
9913 g_assert (boxed_error != NULL);
9915 if (mono_class_has_failure (klass))
9918 mono_loader_lock ();
9919 klass->has_failure = 1;
9920 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, boxed_error);
9921 mono_loader_unlock ();
9927 mono_class_has_failure (const MonoClass *klass)
9929 g_assert (klass != NULL);
9930 return klass->has_failure != 0;
9935 * mono_class_set_type_load_failure:
9936 * @klass: class in which the failure was detected
9937 * @fmt: Printf-style error message string.
9939 * Collect detected failure informaion in the class for later processing.
9940 * The error is stored as a MonoErrorBoxed as with mono_error_set_type_load_class ()
9941 * Note that only the first failure is kept.
9943 * Returns FALSE if a failure was already set on the class, or TRUE otherwise.
9945 * LOCKING: Acquires the loader lock.
9948 mono_class_set_type_load_failure (MonoClass *klass, const char * fmt, ...)
9950 MonoError prepare_error;
9953 if (mono_class_has_failure (klass))
9956 mono_error_init (&prepare_error);
9958 va_start (args, fmt);
9959 mono_error_vset_type_load_class (&prepare_error, klass, fmt, args);
9962 MonoErrorBoxed *box = mono_error_box (&prepare_error, klass->image);
9963 mono_error_cleanup (&prepare_error);
9964 return mono_class_set_failure (klass, box);
9968 * mono_class_get_exception_data:
9970 * Return the exception_data property of KLASS.
9972 * LOCKING: Acquires the loader lock.
9975 mono_class_get_exception_data (const MonoClass *klass)
9977 return mono_image_property_lookup (klass->image, (MonoClass*)klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9981 * mono_classes_init:
9983 * Initialize the resources used by this module.
9986 mono_classes_init (void)
9988 mono_os_mutex_init (&classes_mutex);
9990 mono_counters_register ("Inflated methods size",
9991 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9992 mono_counters_register ("Inflated classes",
9993 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9994 mono_counters_register ("Inflated classes size",
9995 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9996 mono_counters_register ("MonoClass size",
9997 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9998 mono_counters_register ("MonoClassExt size",
9999 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
10003 * mono_classes_cleanup:
10005 * Free the resources used by this module.
10008 mono_classes_cleanup (void)
10010 if (global_interface_bitset)
10011 mono_bitset_free (global_interface_bitset);
10012 global_interface_bitset = NULL;
10013 mono_os_mutex_destroy (&classes_mutex);
10017 * mono_class_get_exception_for_failure:
10018 * @klass: class in which the failure was detected
10020 * Return a constructed MonoException than the caller can then throw
10021 * using mono_raise_exception - or NULL if no failure is present (or
10022 * doesn't result in an exception).
10025 mono_class_get_exception_for_failure (MonoClass *klass)
10027 if (!mono_class_has_failure (klass))
10029 MonoError unboxed_error;
10030 mono_error_init (&unboxed_error);
10031 mono_error_set_for_class_failure (&unboxed_error, klass);
10032 return mono_error_convert_to_exception (&unboxed_error);
10036 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
10038 outer_klass = mono_class_get_generic_type_definition (outer_klass);
10039 inner_klass = mono_class_get_generic_type_definition (inner_klass);
10041 if (outer_klass == inner_klass)
10043 inner_klass = inner_klass->nested_in;
10044 } while (inner_klass);
10049 mono_class_get_generic_type_definition (MonoClass *klass)
10051 return klass->generic_class ? klass->generic_class->container_class : klass;
10055 * Check if @klass is a subtype of @parent ignoring generic instantiations.
10057 * Generic instantiations are ignored for all super types of @klass.
10059 * Visibility checks ignoring generic instantiations.
10062 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
10065 klass = mono_class_get_generic_type_definition (klass);
10066 parent = mono_class_get_generic_type_definition (parent);
10067 mono_class_setup_supertypes (klass);
10069 for (i = 0; i < klass->idepth; ++i) {
10070 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
10076 * Subtype can only access parent members with family protection if the site object
10077 * is subclass of Subtype. For example:
10078 * class A { protected int x; }
10080 * void valid_access () {
10084 * void invalid_access () {
10091 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
10093 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
10096 if (context_klass == NULL)
10098 /*if access_klass is not member_klass context_klass must be type compat*/
10099 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10105 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10108 if (accessing == accessed)
10110 if (!accessed || !accessing)
10113 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10114 * anywhere so untrusted friends are not safe to access platform's code internals */
10115 if (mono_security_core_clr_enabled ()) {
10116 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10120 mono_assembly_load_friends (accessed);
10121 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10122 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10123 /* Be conservative with checks */
10124 if (!friend_->name)
10126 if (strcmp (accessing->aname.name, friend_->name))
10128 if (friend_->public_key_token [0]) {
10129 if (!accessing->aname.public_key_token [0])
10131 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10140 * If klass is a generic type or if it is derived from a generic type, return the
10141 * MonoClass of the generic definition
10142 * Returns NULL if not found
10145 get_generic_definition_class (MonoClass *klass)
10148 if (klass->generic_class && klass->generic_class->container_class)
10149 return klass->generic_class->container_class;
10150 klass = klass->parent;
10156 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10159 for (i = 0; i < ginst->type_argc; ++i) {
10160 MonoType *type = ginst->type_argv[i];
10161 switch (type->type) {
10162 case MONO_TYPE_SZARRAY:
10163 if (!can_access_type (access_klass, type->data.klass))
10166 case MONO_TYPE_ARRAY:
10167 if (!can_access_type (access_klass, type->data.array->eklass))
10170 case MONO_TYPE_PTR:
10171 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10174 case MONO_TYPE_CLASS:
10175 case MONO_TYPE_VALUETYPE:
10176 case MONO_TYPE_GENERICINST:
10177 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10187 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10191 if (access_klass == member_klass)
10194 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10197 if (access_klass->element_class && !access_klass->enumtype)
10198 access_klass = access_klass->element_class;
10200 if (member_klass->element_class && !member_klass->enumtype)
10201 member_klass = member_klass->element_class;
10203 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10205 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10208 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
10211 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10214 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10217 /*Non nested type with nested visibility. We just fail it.*/
10218 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10221 switch (access_level) {
10222 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10223 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10225 case TYPE_ATTRIBUTE_PUBLIC:
10228 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10231 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10232 return is_nesting_type (member_klass, access_klass);
10234 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10235 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10237 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10238 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10240 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10241 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10242 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10244 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10245 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10246 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10251 /* FIXME: check visibility of type, too */
10253 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10255 MonoClass *member_generic_def;
10256 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10259 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
10260 access_klass->generic_container) &&
10261 (member_generic_def = get_generic_definition_class (member_klass))) {
10262 MonoClass *access_container;
10264 if (access_klass->generic_container)
10265 access_container = access_klass;
10267 access_container = access_klass->generic_class->container_class;
10269 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10273 /* Partition I 8.5.3.2 */
10274 /* the access level values are the same for fields and methods */
10275 switch (access_level) {
10276 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10277 /* same compilation unit */
10278 return access_klass->image == member_klass->image;
10279 case FIELD_ATTRIBUTE_PRIVATE:
10280 return access_klass == member_klass;
10281 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10282 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10283 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10286 case FIELD_ATTRIBUTE_ASSEMBLY:
10287 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10288 case FIELD_ATTRIBUTE_FAMILY:
10289 if (is_valid_family_access (access_klass, member_klass, context_klass))
10292 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10293 if (is_valid_family_access (access_klass, member_klass, context_klass))
10295 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10296 case FIELD_ATTRIBUTE_PUBLIC:
10303 * mono_method_can_access_field:
10304 * @method: Method that will attempt to access the field
10305 * @field: the field to access
10307 * Used to determine if a method is allowed to access the specified field.
10309 * Returns: TRUE if the given @method is allowed to access the @field while following
10310 * the accessibility rules of the CLI.
10313 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10315 /* FIXME: check all overlapping fields */
10316 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10318 MonoClass *nested = method->klass->nested_in;
10320 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10323 nested = nested->nested_in;
10330 * mono_method_can_access_method:
10331 * @method: Method that will attempt to access the other method
10332 * @called: the method that we want to probe for accessibility.
10334 * Used to determine if the @method is allowed to access the specified @called method.
10336 * Returns: TRUE if the given @method is allowed to invoke the @called while following
10337 * the accessibility rules of the CLI.
10340 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10342 method = mono_method_get_method_definition (method);
10343 called = mono_method_get_method_definition (called);
10344 return mono_method_can_access_method_full (method, called, NULL);
10348 * mono_method_can_access_method_full:
10349 * @method: The caller method
10350 * @called: The called method
10351 * @context_klass: The static type on stack of the owner @called object used
10353 * This function must be used with instance calls, as they have more strict family accessibility.
10354 * It can be used with static methods, but context_klass should be NULL.
10356 * Returns: TRUE if caller have proper visibility and acessibility to @called
10359 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10361 /* Wrappers are except from access checks */
10362 if (method->wrapper_type != MONO_WRAPPER_NONE || called->wrapper_type != MONO_WRAPPER_NONE)
10365 MonoClass *access_class = method->klass;
10366 MonoClass *member_class = called->klass;
10367 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10369 MonoClass *nested = access_class->nested_in;
10371 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10374 nested = nested->nested_in;
10381 can = can_access_type (access_class, member_class);
10383 MonoClass *nested = access_class->nested_in;
10385 can = can_access_type (nested, member_class);
10388 nested = nested->nested_in;
10395 if (called->is_inflated) {
10396 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10397 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10406 * mono_method_can_access_field_full:
10407 * @method: The caller method
10408 * @field: The accessed field
10409 * @context_klass: The static type on stack of the owner @field object used
10411 * This function must be used with instance fields, as they have more strict family accessibility.
10412 * It can be used with static fields, but context_klass should be NULL.
10414 * Returns: TRUE if caller have proper visibility and acessibility to @field
10417 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10419 MonoClass *access_class = method->klass;
10420 MonoClass *member_class = field->parent;
10421 /* FIXME: check all overlapping fields */
10422 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10424 MonoClass *nested = access_class->nested_in;
10426 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10429 nested = nested->nested_in;
10436 can = can_access_type (access_class, member_class);
10438 MonoClass *nested = access_class->nested_in;
10440 can = can_access_type (nested, member_class);
10443 nested = nested->nested_in;
10453 * mono_class_can_access_class:
10454 * @source_class: The source class
10455 * @target_class: The accessed class
10457 * This function returns is @target_class is visible to @source_class
10459 * Returns: TRUE if source have proper visibility and acessibility to target
10462 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10464 return can_access_type (source_class, target_class);
10468 * mono_type_is_valid_enum_basetype:
10469 * @type: The MonoType to check
10471 * Returns: TRUE if the type can be used as the basetype of an enum
10473 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10474 switch (type->type) {
10477 case MONO_TYPE_BOOLEAN:
10480 case MONO_TYPE_CHAR:
10494 * mono_class_is_valid_enum:
10495 * @klass: An enum class to be validated
10497 * This method verify the required properties an enum should have.
10499 * Returns: TRUE if the informed enum class is valid
10501 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10502 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10503 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10505 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10506 MonoClassField * field;
10507 gpointer iter = NULL;
10508 gboolean found_base_field = FALSE;
10510 g_assert (klass->enumtype);
10511 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10512 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10516 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10519 while ((field = mono_class_get_fields (klass, &iter))) {
10520 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10521 if (found_base_field)
10523 found_base_field = TRUE;
10524 if (!mono_type_is_valid_enum_basetype (field->type))
10529 if (!found_base_field)
10532 if (klass->method.count > 0)
10539 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10541 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10545 * mono_class_setup_interface_id:
10547 * Initializes MonoClass::interface_id if required.
10549 * LOCKING: Acquires the loader lock.
10552 mono_class_setup_interface_id (MonoClass *klass)
10554 mono_loader_lock ();
10555 if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10556 klass->interface_id = mono_get_unique_iid (klass);
10557 mono_loader_unlock ();
10561 * mono_class_alloc_ext:
10563 * Allocate klass->ext if not already done.
10566 mono_class_alloc_ext (MonoClass *klass)
10573 ext = (MonoClassExt *)mono_class_alloc0 (klass, sizeof (MonoClassExt));
10574 mono_image_lock (klass->image);
10575 mono_memory_barrier ();
10578 class_ext_size += sizeof (MonoClassExt);
10579 mono_image_unlock (klass->image);
10583 * mono_class_setup_interfaces:
10585 * Initialize klass->interfaces/interfaces_count.
10586 * LOCKING: Acquires the loader lock.
10587 * This function can fail the type.
10590 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10592 int i, interface_count;
10593 MonoClass **interfaces;
10595 mono_error_init (error);
10597 if (klass->interfaces_inited)
10600 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10601 MonoType *args [1];
10603 /* generic IList, ICollection, IEnumerable */
10604 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10605 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10607 args [0] = &klass->element_class->byval_arg;
10608 interfaces [0] = mono_class_bind_generic_parameters (
10609 mono_defaults.generic_ilist_class, 1, args, FALSE);
10610 if (interface_count > 1)
10611 interfaces [1] = mono_class_bind_generic_parameters (
10612 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10613 } else if (klass->generic_class) {
10614 MonoClass *gklass = klass->generic_class->container_class;
10616 mono_class_setup_interfaces (gklass, error);
10617 if (!mono_error_ok (error)) {
10618 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10622 interface_count = gklass->interface_count;
10623 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10624 for (i = 0; i < interface_count; i++) {
10625 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10626 if (!mono_error_ok (error)) {
10627 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10632 interface_count = 0;
10636 mono_image_lock (klass->image);
10638 if (!klass->interfaces_inited) {
10639 klass->interface_count = interface_count;
10640 klass->interfaces = interfaces;
10642 mono_memory_barrier ();
10644 klass->interfaces_inited = TRUE;
10647 mono_image_unlock (klass->image);
10651 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10653 MonoClass *klass = field->parent;
10654 MonoImage *image = klass->image;
10655 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10656 int field_idx = field - klass->fields;
10658 mono_error_init (error);
10661 MonoClassField *gfield = >d->fields [field_idx];
10662 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10663 if (!mono_error_ok (error)) {
10664 mono_class_set_type_load_failure (klass, "Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10667 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10668 if (!mono_error_ok (error)) {
10669 mono_class_set_type_load_failure (klass, "Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10673 guint32 cols [MONO_FIELD_SIZE];
10674 MonoGenericContainer *container = NULL;
10675 int idx = klass->field.first + field_idx;
10677 /*FIXME, in theory we do not lazy load SRE fields*/
10678 g_assert (!image_is_dynamic (image));
10680 if (klass->generic_container) {
10681 container = klass->generic_container;
10683 container = gtd->generic_container;
10684 g_assert (container);
10687 /* klass->field.first and idx points into the fieldptr table */
10688 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10690 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10691 mono_error_set_type_load_class (error, klass, "Could not verify field %s signature", field->name);;
10692 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
10696 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10698 mono_metadata_decode_value (sig, &sig);
10699 /* FIELD signature == 0x06 */
10700 g_assert (*sig == 0x06);
10702 field->type = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10703 if (!field->type) {
10704 mono_class_set_type_load_failure (klass, "Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10710 mono_field_resolve_flags (MonoClassField *field)
10712 MonoClass *klass = field->parent;
10713 MonoImage *image = klass->image;
10714 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10715 int field_idx = field - klass->fields;
10719 MonoClassField *gfield = >d->fields [field_idx];
10720 return mono_field_get_flags (gfield);
10722 int idx = klass->field.first + field_idx;
10724 /*FIXME, in theory we do not lazy load SRE fields*/
10725 g_assert (!image_is_dynamic (image));
10727 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10732 * mono_class_setup_basic_field_info:
10733 * @class: The class to initialize
10735 * Initializes the klass->fields array of fields.
10736 * Aquires the loader lock.
10739 mono_class_setup_basic_field_info_locking (MonoClass *klass)
10741 mono_loader_lock ();
10742 mono_class_setup_basic_field_info (klass);
10743 mono_loader_unlock ();
10747 * mono_class_get_fields_lazy:
10748 * @klass: the MonoClass to act on
10750 * This routine is an iterator routine for retrieving the fields in a class.
10751 * Only minimal information about fields are loaded. Accessors must be used
10752 * for all MonoClassField returned.
10754 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10755 * iterate over all of the elements. When no more values are
10756 * available, the return value is NULL.
10758 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10761 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10763 MonoClassField* field;
10767 mono_class_setup_basic_field_info_locking (klass);
10768 if (!klass->fields)
10770 /* start from the first */
10771 if (klass->field.count) {
10772 *iter = &klass->fields [0];
10773 return (MonoClassField *)*iter;
10779 field = (MonoClassField *)*iter;
10781 if (field < &klass->fields [klass->field.count]) {
10783 return (MonoClassField *)*iter;
10789 mono_class_full_name (MonoClass *klass)
10791 return mono_type_full_name (&klass->byval_arg);
10794 /* Declare all shared lazy type lookup functions */
10795 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, System.Runtime.InteropServices, SafeHandle)