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 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6414 result->cast_class = result->element_class = el_class;
6415 result->blittable = TRUE;
6417 result->byval_arg.type = MONO_TYPE_PTR;
6418 result->this_arg.type = result->byval_arg.type;
6419 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6420 result->this_arg.byref = TRUE;
6422 mono_class_setup_supertypes (result);
6424 mono_image_lock (image);
6425 if (image->ptr_cache) {
6427 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6428 mono_image_unlock (image);
6429 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6433 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6435 g_hash_table_insert (image->ptr_cache, el_class, result);
6436 mono_image_unlock (image);
6438 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6444 mono_fnptr_class_get (MonoMethodSignature *sig)
6447 static GHashTable *ptr_hash = NULL;
6449 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6451 mono_loader_lock ();
6454 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6456 if ((result = (MonoClass *)g_hash_table_lookup (ptr_hash, sig))) {
6457 mono_loader_unlock ();
6460 result = g_new0 (MonoClass, 1);
6462 result->parent = NULL; /* no parent for PTR types */
6463 result->name_space = "System";
6464 result->name = "MonoFNPtrFakeClass";
6466 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6468 result->image = mono_defaults.corlib; /* need to fix... */
6469 result->inited = TRUE;
6470 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6471 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6472 result->cast_class = result->element_class = result;
6473 result->blittable = TRUE;
6475 result->byval_arg.type = MONO_TYPE_FNPTR;
6476 result->this_arg.type = result->byval_arg.type;
6477 result->this_arg.data.method = result->byval_arg.data.method = sig;
6478 result->this_arg.byref = TRUE;
6479 result->blittable = TRUE;
6481 mono_class_setup_supertypes (result);
6483 g_hash_table_insert (ptr_hash, sig, result);
6485 mono_loader_unlock ();
6487 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6493 * mono_class_from_mono_type:
6494 * @type: describes the type to return
6496 * This returns a MonoClass for the specified MonoType, the value is never NULL.
6499 mono_class_from_mono_type (MonoType *type)
6501 switch (type->type) {
6502 case MONO_TYPE_OBJECT:
6503 return type->data.klass? type->data.klass: mono_defaults.object_class;
6504 case MONO_TYPE_VOID:
6505 return type->data.klass? type->data.klass: mono_defaults.void_class;
6506 case MONO_TYPE_BOOLEAN:
6507 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6508 case MONO_TYPE_CHAR:
6509 return type->data.klass? type->data.klass: mono_defaults.char_class;
6511 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6513 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6515 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6517 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6519 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6521 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6523 return type->data.klass? type->data.klass: mono_defaults.int_class;
6525 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6527 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6529 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6531 return type->data.klass? type->data.klass: mono_defaults.single_class;
6533 return type->data.klass? type->data.klass: mono_defaults.double_class;
6534 case MONO_TYPE_STRING:
6535 return type->data.klass? type->data.klass: mono_defaults.string_class;
6536 case MONO_TYPE_TYPEDBYREF:
6537 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6538 case MONO_TYPE_ARRAY:
6539 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6541 return mono_ptr_class_get (type->data.type);
6542 case MONO_TYPE_FNPTR:
6543 return mono_fnptr_class_get (type->data.method);
6544 case MONO_TYPE_SZARRAY:
6545 return mono_array_class_get (type->data.klass, 1);
6546 case MONO_TYPE_CLASS:
6547 case MONO_TYPE_VALUETYPE:
6548 return type->data.klass;
6549 case MONO_TYPE_GENERICINST:
6550 return mono_generic_class_get_class (type->data.generic_class);
6551 case MONO_TYPE_MVAR:
6553 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6555 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6556 g_assert_not_reached ();
6559 // Yes, this returns NULL, even if it is documented as not doing so, but there
6560 // is no way for the code to make it this far, due to the assert above.
6565 * mono_type_retrieve_from_typespec
6566 * @image: context where the image is created
6567 * @type_spec: typespec token
6568 * @context: the generic context used to evaluate generic instantiations in
6571 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6573 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6575 *did_inflate = FALSE;
6580 if (context && (context->class_inst || context->method_inst)) {
6581 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6583 if (!mono_error_ok (error)) {
6589 *did_inflate = TRUE;
6596 * mono_class_create_from_typespec
6597 * @image: context where the image is created
6598 * @type_spec: typespec token
6599 * @context: the generic context used to evaluate generic instantiations in
6602 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6605 gboolean inflated = FALSE;
6606 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6607 return_val_if_nok (error, NULL);
6608 ret = mono_class_from_mono_type (t);
6610 mono_metadata_free_type (t);
6615 * mono_bounded_array_class_get:
6616 * @element_class: element class
6617 * @rank: the dimension of the array class
6618 * @bounded: whenever the array has non-zero bounds
6620 * Returns: A class object describing the array with element type @element_type and
6624 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6628 MonoClass *parent = NULL;
6629 GSList *list, *rootlist = NULL;
6632 gboolean corlib_type = FALSE;
6634 g_assert (rank <= 255);
6637 /* bounded only matters for one-dimensional arrays */
6640 image = eclass->image;
6642 if (rank == 1 && !bounded) {
6644 * This case is very frequent not just during compilation because of calls
6645 * from mono_class_from_mono_type (), mono_array_new (),
6646 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6648 mono_os_mutex_lock (&image->szarray_cache_lock);
6649 if (!image->szarray_cache)
6650 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6651 klass = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6652 mono_os_mutex_unlock (&image->szarray_cache_lock);
6656 mono_loader_lock ();
6658 mono_loader_lock ();
6660 if (!image->array_cache)
6661 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6663 if ((rootlist = list = (GSList *)g_hash_table_lookup (image->array_cache, eclass))) {
6664 for (; list; list = list->next) {
6665 klass = (MonoClass *)list->data;
6666 if ((klass->rank == rank) && (klass->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6667 mono_loader_unlock ();
6674 /* for the building corlib use System.Array from it */
6675 if (image->assembly && assembly_is_dynamic (image->assembly) && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6676 parent = mono_class_load_from_name (image, "System", "Array");
6679 parent = mono_defaults.array_class;
6680 if (!parent->inited)
6681 mono_class_init (parent);
6684 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6686 klass->image = image;
6687 klass->name_space = eclass->name_space;
6688 nsize = strlen (eclass->name);
6689 name = (char *)g_malloc (nsize + 2 + rank + 1);
6690 memcpy (name, eclass->name, nsize);
6693 memset (name + nsize + 1, ',', rank - 1);
6695 name [nsize + rank] = '*';
6696 name [nsize + rank + bounded] = ']';
6697 name [nsize + rank + bounded + 1] = 0;
6698 klass->name = mono_image_strdup (image, name);
6701 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6703 classes_size += sizeof (MonoClass);
6705 klass->type_token = 0;
6706 /* all arrays are marked serializable and sealed, bug #42779 */
6707 klass->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6708 klass->parent = parent;
6709 klass->instance_size = mono_class_instance_size (klass->parent);
6711 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6712 /*Arrays of those two types are invalid.*/
6713 MonoError prepared_error;
6714 mono_error_init (&prepared_error);
6715 mono_error_set_invalid_program (&prepared_error, "Arrays of void or System.TypedReference types are invalid.");
6716 mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6717 mono_error_cleanup (&prepared_error);
6718 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6719 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6720 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6721 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6723 /* element_size -1 is ok as this is not an instantitable type*/
6724 klass->sizes.element_size = -1;
6726 klass->sizes.element_size = mono_class_array_element_size (eclass);
6728 mono_class_setup_supertypes (klass);
6730 if (eclass->generic_class)
6731 mono_class_init (eclass);
6732 if (!eclass->size_inited)
6733 mono_class_setup_fields (eclass);
6734 mono_class_set_type_load_failure_causedby_class (klass, eclass, "Could not load array element type");
6735 /*FIXME we fail the array type, but we have to let other fields be set.*/
6737 klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6741 if (eclass->enumtype)
6742 klass->cast_class = eclass->element_class;
6744 klass->cast_class = eclass;
6746 switch (klass->cast_class->byval_arg.type) {
6748 klass->cast_class = mono_defaults.byte_class;
6751 klass->cast_class = mono_defaults.int16_class;
6754 #if SIZEOF_VOID_P == 4
6758 klass->cast_class = mono_defaults.int32_class;
6761 #if SIZEOF_VOID_P == 8
6765 klass->cast_class = mono_defaults.int64_class;
6771 klass->element_class = eclass;
6773 if ((rank > 1) || bounded) {
6774 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6775 klass->byval_arg.type = MONO_TYPE_ARRAY;
6776 klass->byval_arg.data.array = at;
6777 at->eklass = eclass;
6779 /* FIXME: complete.... */
6781 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6782 klass->byval_arg.data.klass = eclass;
6784 klass->this_arg = klass->byval_arg;
6785 klass->this_arg.byref = 1;
6790 klass->generic_container = eclass->generic_container;
6792 if (rank == 1 && !bounded) {
6793 MonoClass *prev_class;
6795 mono_os_mutex_lock (&image->szarray_cache_lock);
6796 prev_class = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6798 /* Someone got in before us */
6801 g_hash_table_insert (image->szarray_cache, eclass, klass);
6802 mono_os_mutex_unlock (&image->szarray_cache_lock);
6804 list = g_slist_append (rootlist, klass);
6805 g_hash_table_insert (image->array_cache, eclass, list);
6808 mono_loader_unlock ();
6810 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6816 * mono_array_class_get:
6817 * @element_class: element class
6818 * @rank: the dimension of the array class
6820 * Returns: A class object describing the array with element type @element_type and
6824 mono_array_class_get (MonoClass *eclass, guint32 rank)
6826 return mono_bounded_array_class_get (eclass, rank, FALSE);
6830 * mono_class_instance_size:
6833 * Use to get the size of a class in bytes.
6835 * Returns: The size of an object instance
6838 mono_class_instance_size (MonoClass *klass)
6840 if (!klass->size_inited)
6841 mono_class_init (klass);
6843 return klass->instance_size;
6847 * mono_class_min_align:
6850 * Use to get the computed minimum alignment requirements for the specified class.
6852 * Returns: minimm alignment requirements
6855 mono_class_min_align (MonoClass *klass)
6857 if (!klass->size_inited)
6858 mono_class_init (klass);
6860 return klass->min_align;
6864 * mono_class_value_size:
6867 * This function is used for value types, and return the
6868 * space and the alignment to store that kind of value object.
6870 * Returns: the size of a value of kind @klass
6873 mono_class_value_size (MonoClass *klass, guint32 *align)
6877 /* fixme: check disable, because we still have external revereces to
6878 * mscorlib and Dummy Objects
6880 /*g_assert (klass->valuetype);*/
6882 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6885 *align = klass->min_align;
6891 * mono_class_data_size:
6894 * Returns: The size of the static class data
6897 mono_class_data_size (MonoClass *klass)
6900 mono_class_init (klass);
6901 /* This can happen with dynamically created types */
6902 if (!klass->fields_inited)
6903 mono_class_setup_fields_locking (klass);
6905 /* in arrays, sizes.class_size is unioned with element_size
6906 * and arrays have no static fields
6910 return klass->sizes.class_size;
6914 * Auxiliary routine to mono_class_get_field
6916 * Takes a field index instead of a field token.
6918 static MonoClassField *
6919 mono_class_get_field_idx (MonoClass *klass, int idx)
6921 mono_class_setup_fields_locking (klass);
6922 if (mono_class_has_failure (klass))
6926 if (klass->image->uncompressed_metadata) {
6928 * klass->field.first points to the FieldPtr table, while idx points into the
6929 * Field table, so we have to do a search.
6931 /*FIXME this is broken for types with multiple fields with the same name.*/
6932 const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6935 for (i = 0; i < klass->field.count; ++i)
6936 if (mono_field_get_name (&klass->fields [i]) == name)
6937 return &klass->fields [i];
6938 g_assert_not_reached ();
6940 if (klass->field.count) {
6941 if ((idx >= klass->field.first) && (idx < klass->field.first + klass->field.count)){
6942 return &klass->fields [idx - klass->field.first];
6946 klass = klass->parent;
6952 * mono_class_get_field:
6953 * @class: the class to lookup the field.
6954 * @field_token: the field token
6956 * Returns: A MonoClassField representing the type and offset of
6957 * the field, or a NULL value if the field does not belong to this
6961 mono_class_get_field (MonoClass *klass, guint32 field_token)
6963 int idx = mono_metadata_token_index (field_token);
6965 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6967 return mono_class_get_field_idx (klass, idx - 1);
6971 * mono_class_get_field_from_name:
6972 * @klass: the class to lookup the field.
6973 * @name: the field name
6975 * Search the class @klass and it's parents for a field with the name @name.
6977 * Returns: The MonoClassField pointer of the named field or NULL
6980 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6982 return mono_class_get_field_from_name_full (klass, name, NULL);
6986 * mono_class_get_field_from_name_full:
6987 * @klass: the class to lookup the field.
6988 * @name: the field name
6989 * @type: the type of the fields. This optional.
6991 * Search the class @klass and it's parents for a field with the name @name and type @type.
6993 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
6994 * of its generic type definition.
6996 * Returns: The MonoClassField pointer of the named field or NULL
6999 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
7003 mono_class_setup_fields_locking (klass);
7004 if (mono_class_has_failure (klass))
7008 for (i = 0; i < klass->field.count; ++i) {
7009 MonoClassField *field = &klass->fields [i];
7011 if (strcmp (name, mono_field_get_name (field)) != 0)
7015 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
7016 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
7021 klass = klass->parent;
7027 * mono_class_get_field_token:
7028 * @field: the field we need the token of
7030 * Get the token of a field. Note that the tokesn is only valid for the image
7031 * the field was loaded from. Don't use this function for fields in dynamic types.
7033 * Returns: The token representing the field in the image it was loaded from.
7036 mono_class_get_field_token (MonoClassField *field)
7038 MonoClass *klass = field->parent;
7041 mono_class_setup_fields_locking (klass);
7046 for (i = 0; i < klass->field.count; ++i) {
7047 if (&klass->fields [i] == field) {
7048 int idx = klass->field.first + i + 1;
7050 if (klass->image->uncompressed_metadata)
7051 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
7052 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
7055 klass = klass->parent;
7058 g_assert_not_reached ();
7063 mono_field_get_index (MonoClassField *field)
7065 int index = field - field->parent->fields;
7067 g_assert (index >= 0 && index < field->parent->field.count);
7073 * mono_class_get_field_default_value:
7075 * Return the default value of the field as a pointer into the metadata blob.
7078 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
7081 guint32 constant_cols [MONO_CONSTANT_SIZE];
7083 MonoClass *klass = field->parent;
7085 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7087 if (!klass->ext || !klass->ext->field_def_values) {
7088 MonoFieldDefaultValue *def_values;
7090 mono_class_alloc_ext (klass);
7092 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
7094 mono_image_lock (klass->image);
7095 mono_memory_barrier ();
7096 if (!klass->ext->field_def_values)
7097 klass->ext->field_def_values = def_values;
7098 mono_image_unlock (klass->image);
7101 field_index = mono_field_get_index (field);
7103 if (!klass->ext->field_def_values [field_index].data) {
7104 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7108 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7110 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7111 klass->ext->field_def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7112 klass->ext->field_def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7115 *def_type = klass->ext->field_def_values [field_index].def_type;
7116 return klass->ext->field_def_values [field_index].data;
7120 mono_property_get_index (MonoProperty *prop)
7122 int index = prop - prop->parent->ext->properties;
7124 g_assert (index >= 0 && index < prop->parent->ext->property.count);
7130 * mono_class_get_property_default_value:
7132 * Return the default value of the field as a pointer into the metadata blob.
7135 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7138 guint32 constant_cols [MONO_CONSTANT_SIZE];
7139 MonoClass *klass = property->parent;
7141 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7143 * We don't cache here because it is not used by C# so it's quite rare, but
7144 * we still do the lookup in klass->ext because that is where the data
7145 * is stored for dynamic assemblies.
7148 if (image_is_dynamic (klass->image)) {
7149 int prop_index = mono_property_get_index (property);
7150 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
7151 *def_type = klass->ext->prop_def_values [prop_index].def_type;
7152 return klass->ext->prop_def_values [prop_index].data;
7156 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7160 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7161 *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7162 return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7166 mono_class_get_event_token (MonoEvent *event)
7168 MonoClass *klass = event->parent;
7173 for (i = 0; i < klass->ext->event.count; ++i) {
7174 if (&klass->ext->events [i] == event)
7175 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
7178 klass = klass->parent;
7181 g_assert_not_reached ();
7186 * mono_class_get_property_from_name:
7188 * @name: name of the property to lookup in the specified class
7190 * Use this method to lookup a property in a class
7191 * Returns: the MonoProperty with the given name, or NULL if the property
7192 * does not exist on the @klass.
7195 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7199 gpointer iter = NULL;
7200 while ((p = mono_class_get_properties (klass, &iter))) {
7201 if (! strcmp (name, p->name))
7204 klass = klass->parent;
7210 * mono_class_get_property_token:
7211 * @prop: MonoProperty to query
7213 * Returns: The ECMA token for the specified property.
7216 mono_class_get_property_token (MonoProperty *prop)
7218 MonoClass *klass = prop->parent;
7222 gpointer iter = NULL;
7223 while ((p = mono_class_get_properties (klass, &iter))) {
7224 if (&klass->ext->properties [i] == prop)
7225 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
7229 klass = klass->parent;
7232 g_assert_not_reached ();
7237 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7239 const char *name, *nspace;
7240 if (image_is_dynamic (image))
7241 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7243 switch (type_token & 0xff000000){
7244 case MONO_TOKEN_TYPE_DEF: {
7245 guint32 cols [MONO_TYPEDEF_SIZE];
7246 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7247 guint tidx = mono_metadata_token_index (type_token);
7249 if (tidx > tt->rows)
7250 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7252 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7253 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7254 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7255 if (strlen (nspace) == 0)
7256 return g_strdup_printf ("%s", name);
7258 return g_strdup_printf ("%s.%s", nspace, name);
7261 case MONO_TOKEN_TYPE_REF: {
7263 guint32 cols [MONO_TYPEREF_SIZE];
7264 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7265 guint tidx = mono_metadata_token_index (type_token);
7268 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7270 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7271 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7272 mono_error_cleanup (&error);
7276 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7277 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7278 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7279 if (strlen (nspace) == 0)
7280 return g_strdup_printf ("%s", name);
7282 return g_strdup_printf ("%s.%s", nspace, name);
7285 case MONO_TOKEN_TYPE_SPEC:
7286 return g_strdup_printf ("Typespec 0x%08x", type_token);
7288 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7293 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7295 if (image_is_dynamic (image))
7296 return g_strdup_printf ("DynamicAssembly %s", image->name);
7298 switch (type_token & 0xff000000){
7299 case MONO_TOKEN_TYPE_DEF:
7300 if (image->assembly)
7301 return mono_stringify_assembly_name (&image->assembly->aname);
7302 else if (image->assembly_name)
7303 return g_strdup (image->assembly_name);
7304 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7305 case MONO_TOKEN_TYPE_REF: {
7307 MonoAssemblyName aname;
7308 guint32 cols [MONO_TYPEREF_SIZE];
7309 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7310 guint32 idx = mono_metadata_token_index (type_token);
7313 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7315 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7316 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7317 mono_error_cleanup (&error);
7320 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7322 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7323 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7324 case MONO_RESOLUTION_SCOPE_MODULE:
7326 return g_strdup ("");
7327 case MONO_RESOLUTION_SCOPE_MODULEREF:
7329 return g_strdup ("");
7330 case MONO_RESOLUTION_SCOPE_TYPEREF:
7332 return g_strdup ("");
7333 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7334 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7335 return mono_stringify_assembly_name (&aname);
7337 g_assert_not_reached ();
7341 case MONO_TOKEN_TYPE_SPEC:
7343 return g_strdup ("");
7345 g_assert_not_reached ();
7352 * mono_class_get_full:
7353 * @image: the image where the class resides
7354 * @type_token: the token for the class
7355 * @context: the generic context used to evaluate generic instantiations in
7356 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7358 * Returns: The MonoClass that represents @type_token in @image
7361 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7365 klass = mono_class_get_checked (image, type_token, &error);
7367 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7368 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7370 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7376 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7380 mono_error_init (error);
7381 klass = mono_class_get_checked (image, type_token, error);
7383 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7384 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7389 * mono_class_get_checked:
7390 * @image: the image where the class resides
7391 * @type_token: the token for the class
7392 * @error: error object to return any error
7394 * Returns: The MonoClass that represents @type_token in @image, or NULL on error.
7397 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7399 MonoClass *klass = NULL;
7401 mono_error_init (error);
7403 if (image_is_dynamic (image)) {
7404 int table = mono_metadata_token_table (type_token);
7406 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7407 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7410 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
7414 switch (type_token & 0xff000000){
7415 case MONO_TOKEN_TYPE_DEF:
7416 klass = mono_class_create_from_typedef (image, type_token, error);
7418 case MONO_TOKEN_TYPE_REF:
7419 klass = mono_class_from_typeref_checked (image, type_token, error);
7421 case MONO_TOKEN_TYPE_SPEC:
7422 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7425 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7429 /* Generic case, should be avoided for when a better error is possible. */
7430 if (!klass && mono_error_ok (error)) {
7431 char *name = mono_class_name_from_token (image, type_token);
7432 char *assembly = mono_assembly_name_from_token (image, type_token);
7433 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7441 * mono_type_get_checked:
7442 * @image: the image where the type resides
7443 * @type_token: the token for the type
7444 * @context: the generic context used to evaluate generic instantiations in
7445 * @error: Error handling context
7447 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7449 * Returns: The MonoType that represents @type_token in @image
7452 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7454 MonoType *type = NULL;
7455 gboolean inflated = FALSE;
7457 mono_error_init (error);
7459 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7460 if (image_is_dynamic (image)) {
7461 MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
7462 return_val_if_nok (error, NULL);
7463 return mono_class_get_type (klass);
7466 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7467 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7474 return mono_class_get_type (klass);
7477 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7484 MonoType *tmp = type;
7485 type = mono_class_get_type (mono_class_from_mono_type (type));
7486 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7487 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7488 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7490 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7492 if (type->type != tmp->type)
7495 mono_metadata_free_type (tmp);
7502 * @image: image where the class token will be looked up.
7503 * @type_token: a type token from the image
7505 * Returns the MonoClass with the given @type_token on the @image
7508 mono_class_get (MonoImage *image, guint32 type_token)
7510 return mono_class_get_full (image, type_token, NULL);
7514 * mono_image_init_name_cache:
7516 * Initializes the class name cache stored in image->name_cache.
7518 * LOCKING: Acquires the corresponding image lock.
7521 mono_image_init_name_cache (MonoImage *image)
7523 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7524 guint32 cols [MONO_TYPEDEF_SIZE];
7527 guint32 i, visib, nspace_index;
7528 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7530 if (image->name_cache)
7533 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7535 if (image_is_dynamic (image)) {
7536 mono_image_lock (image);
7537 if (image->name_cache) {
7538 /* Somebody initialized it before us */
7539 g_hash_table_destroy (the_name_cache);
7541 mono_atomic_store_release (&image->name_cache, the_name_cache);
7543 mono_image_unlock (image);
7547 /* Temporary hash table to avoid lookups in the nspace_table */
7548 name_cache2 = g_hash_table_new (NULL, NULL);
7550 for (i = 1; i <= t->rows; ++i) {
7551 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7552 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7554 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7555 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7557 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7559 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7560 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7562 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7563 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7564 if (!nspace_table) {
7565 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7566 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7567 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7570 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7573 /* Load type names from EXPORTEDTYPES table */
7575 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7576 guint32 cols [MONO_EXP_TYPE_SIZE];
7579 for (i = 0; i < t->rows; ++i) {
7580 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7582 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7583 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7587 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7588 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7590 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7591 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7592 if (!nspace_table) {
7593 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7594 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7595 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7598 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7602 g_hash_table_destroy (name_cache2);
7604 mono_image_lock (image);
7605 if (image->name_cache) {
7606 /* Somebody initialized it before us */
7607 g_hash_table_destroy (the_name_cache);
7609 mono_atomic_store_release (&image->name_cache, the_name_cache);
7611 mono_image_unlock (image);
7614 /*FIXME Only dynamic assemblies should allow this operation.*/
7616 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7617 const char *name, guint32 index)
7619 GHashTable *nspace_table;
7620 GHashTable *name_cache;
7623 mono_image_init_name_cache (image);
7624 mono_image_lock (image);
7626 name_cache = image->name_cache;
7627 if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7628 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7629 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7632 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7633 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7635 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7637 mono_image_unlock (image);
7646 find_nocase (gpointer key, gpointer value, gpointer user_data)
7648 char *name = (char*)key;
7649 FindUserData *data = (FindUserData*)user_data;
7651 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7652 data->value = value;
7656 * mono_class_from_name_case:
7657 * @image: The MonoImage where the type is looked up in
7658 * @name_space: the type namespace
7659 * @name: the type short name.
7660 * @deprecated: use the mono_class_from_name_case_checked variant instead.
7662 * Obtains a MonoClass with a given namespace and a given name which
7663 * is located in the given MonoImage. The namespace and name
7664 * lookups are case insensitive.
7667 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7670 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7671 mono_error_cleanup (&error);
7677 * mono_class_from_name_case:
7678 * @image: The MonoImage where the type is looked up in
7679 * @name_space: the type namespace
7680 * @name: the type short name.
7683 * Obtains a MonoClass with a given namespace and a given name which
7684 * is located in the given MonoImage. The namespace and name
7685 * lookups are case insensitive.
7687 * Returns: The MonoClass if the given namespace and name were found, or NULL if it
7688 * was not found. The @error object will contain information about the problem
7692 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7694 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7695 guint32 cols [MONO_TYPEDEF_SIZE];
7700 mono_error_init (error);
7702 if (image_is_dynamic (image)) {
7704 FindUserData user_data;
7706 mono_image_init_name_cache (image);
7707 mono_image_lock (image);
7709 user_data.key = name_space;
7710 user_data.value = NULL;
7711 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7713 if (user_data.value) {
7714 GHashTable *nspace_table = (GHashTable*)user_data.value;
7716 user_data.key = name;
7717 user_data.value = NULL;
7719 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7721 if (user_data.value)
7722 token = GPOINTER_TO_UINT (user_data.value);
7725 mono_image_unlock (image);
7728 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7734 /* add a cache if needed */
7735 for (i = 1; i <= t->rows; ++i) {
7736 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7737 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7739 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7740 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7742 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7744 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7745 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7746 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7747 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7753 return_nested_in (MonoClass *klass, char *nested)
7756 char *s = strchr (nested, '/');
7757 gpointer iter = NULL;
7764 while ((found = mono_class_get_nested_types (klass, &iter))) {
7765 if (strcmp (found->name, nested) == 0) {
7767 return return_nested_in (found, s);
7775 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7777 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7778 MonoImage *file_image;
7782 mono_error_init (error);
7785 * The EXPORTEDTYPES table only contains public types, so have to search the
7787 * Note: image->modules contains the contents of the MODULEREF table, while
7788 * the real module list is in the FILE table.
7790 for (i = 0; i < file_table->rows; i++) {
7791 guint32 cols [MONO_FILE_SIZE];
7792 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7793 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7796 file_image = mono_image_load_file_for_image_checked (image, i + 1, error);
7798 klass = mono_class_from_name_checked (file_image, name_space, name, error);
7799 if (klass || !is_ok (error))
7808 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7810 GHashTable *nspace_table;
7811 MonoImage *loaded_image;
7818 mono_error_init (error);
7820 // Checking visited images avoids stack overflows when cyclic references exist.
7821 if (g_hash_table_lookup (visited_images, image))
7824 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7826 if ((nested = strchr (name, '/'))) {
7827 int pos = nested - name;
7828 int len = strlen (name);
7831 memcpy (buf, name, len + 1);
7833 nested = buf + pos + 1;
7837 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7838 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7839 gboolean res = get_class_from_name (image, name_space, name, &klass);
7842 klass = search_modules (image, name_space, name, error);
7847 return klass ? return_nested_in (klass, nested) : NULL;
7853 mono_image_init_name_cache (image);
7854 mono_image_lock (image);
7856 nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7859 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7861 mono_image_unlock (image);
7863 if (!token && image_is_dynamic (image) && image->modules) {
7864 /* Search modules as well */
7865 for (i = 0; i < image->module_count; ++i) {
7866 MonoImage *module = image->modules [i];
7868 klass = mono_class_from_name_checked (module, name_space, name, error);
7869 if (klass || !is_ok (error))
7875 klass = search_modules (image, name_space, name, error);
7876 if (klass || !is_ok (error))
7881 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7882 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7883 guint32 cols [MONO_EXP_TYPE_SIZE];
7886 idx = mono_metadata_token_index (token);
7888 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7890 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7891 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7892 loaded_image = mono_assembly_load_module_checked (image->assembly, impl >> MONO_IMPLEMENTATION_BITS, error);
7895 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7897 return klass ? return_nested_in (klass, nested) : NULL;
7899 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7900 guint32 assembly_idx;
7902 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7904 mono_assembly_load_reference (image, assembly_idx - 1);
7905 g_assert (image->references [assembly_idx - 1]);
7906 if (image->references [assembly_idx - 1] == (gpointer)-1)
7908 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
7910 return klass ? return_nested_in (klass, nested) : NULL;
7913 g_assert_not_reached ();
7917 token = MONO_TOKEN_TYPE_DEF | token;
7919 klass = mono_class_get_checked (image, token, error);
7921 return return_nested_in (klass, nested);
7926 * mono_class_from_name_checked:
7927 * @image: The MonoImage where the type is looked up in
7928 * @name_space: the type namespace
7929 * @name: the type short name.
7931 * Obtains a MonoClass with a given namespace and a given name which
7932 * is located in the given MonoImage.
7934 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
7935 * set if the class was not found or it will return NULL and set the error if there was a loading error.
7938 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7941 GHashTable *visited_images;
7943 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7945 klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
7947 g_hash_table_destroy (visited_images);
7953 * mono_class_from_name:
7954 * @image: The MonoImage where the type is looked up in
7955 * @name_space: the type namespace
7956 * @name: the type short name.
7958 * Obtains a MonoClass with a given namespace and a given name which
7959 * is located in the given MonoImage.
7961 * To reference nested classes, use the "/" character as a separator.
7962 * For example use "Foo/Bar" to reference the class Bar that is nested
7963 * inside Foo, like this: "class Foo { class Bar {} }".
7966 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7971 klass = mono_class_from_name_checked (image, name_space, name, &error);
7972 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
7978 * mono_class_load_from_name:
7979 * @image: The MonoImage where the type is looked up in
7980 * @name_space: the type namespace
7981 * @name: the type short name.
7983 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
7984 * This function should be used by the runtime for critical types to which there's no way to recover but crash
7985 * If they are missing. Thing of System.Object or System.String.
7988 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
7993 klass = mono_class_from_name_checked (image, name_space, name, &error);
7995 g_error ("Runtime critical type %s.%s not found", name_space, name);
7996 if (!mono_error_ok (&error))
7997 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8002 * mono_class_try_load_from_name:
8003 * @image: The MonoImage where the type is looked up in
8004 * @name_space: the type namespace
8005 * @name: the type short name.
8007 * This function tries to load a type, returning the class was found or NULL otherwise.
8008 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
8010 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
8011 * a type that we would otherwise assume to be available but was not due some error.
8015 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
8020 klass = mono_class_from_name_checked (image, name_space, name, &error);
8021 if (!mono_error_ok (&error))
8022 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8028 * mono_class_is_subclass_of:
8029 * @klass: class to probe if it is a subclass of another one
8030 * @klassc: the class we suspect is the base class
8031 * @check_interfaces: whether we should perform interface checks
8033 * This method determines whether @klass is a subclass of @klassc.
8035 * If the @check_interfaces flag is set, then if @klassc is an interface
8036 * this method return TRUE if the @klass implements the interface or
8037 * if @klass is an interface, if one of its base classes is @klass.
8039 * If @check_interfaces is false then, then if @klass is not an interface
8040 * then it returns TRUE if the @klass is a subclass of @klassc.
8042 * if @klass is an interface and @klassc is System.Object, then this function
8047 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
8048 gboolean check_interfaces)
8050 /* FIXME test for interfaces with variant generic arguments */
8051 mono_class_init (klass);
8052 mono_class_init (klassc);
8054 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
8055 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
8057 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
8060 for (i = 0; i < klass->interface_count; i ++) {
8061 MonoClass *ic = klass->interfaces [i];
8066 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
8071 * MS.NET thinks interfaces are a subclass of Object, so we think it as
8074 if (klassc == mono_defaults.object_class)
8081 mono_type_is_generic_argument (MonoType *type)
8083 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
8087 mono_class_has_variant_generic_params (MonoClass *klass)
8090 MonoGenericContainer *container;
8092 if (!klass->generic_class)
8095 container = klass->generic_class->container_class->generic_container;
8097 for (i = 0; i < container->type_argc; ++i)
8098 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8105 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8107 if (target == candidate)
8110 if (check_for_reference_conv &&
8111 mono_type_is_generic_argument (&target->byval_arg) &&
8112 mono_type_is_generic_argument (&candidate->byval_arg)) {
8113 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8114 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8116 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8119 if (!mono_class_is_assignable_from (target, candidate))
8125 * @container the generic container from the GTD
8126 * @klass: the class to be assigned to
8127 * @oklass: the source class
8129 * Both @klass and @oklass must be instances of the same generic interface.
8131 * Returns: TRUE if @klass can be assigned to a @klass variable
8134 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8137 MonoType **klass_argv, **oklass_argv;
8138 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8139 MonoGenericContainer *container = klass_gtd->generic_container;
8141 if (klass == oklass)
8144 /*Viable candidates are instances of the same generic interface*/
8145 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8148 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8149 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8151 for (j = 0; j < container->type_argc; ++j) {
8152 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8153 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8155 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8159 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8160 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8162 if (param1_class != param2_class) {
8163 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8164 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8166 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8167 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8177 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8179 MonoGenericParam *gparam, *ogparam;
8180 MonoGenericParamInfo *tinfo, *cinfo;
8181 MonoClass **candidate_class;
8182 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8185 if (target == candidate)
8187 if (target->byval_arg.type != candidate->byval_arg.type)
8190 gparam = target->byval_arg.data.generic_param;
8191 ogparam = candidate->byval_arg.data.generic_param;
8192 tinfo = mono_generic_param_info (gparam);
8193 cinfo = mono_generic_param_info (ogparam);
8195 class_constraint_satisfied = FALSE;
8196 valuetype_constraint_satisfied = FALSE;
8198 /*candidate must have a super set of target's special constraints*/
8199 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8200 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8202 if (cinfo->constraints) {
8203 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8204 MonoClass *cc = *candidate_class;
8206 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8207 class_constraint_satisfied = TRUE;
8208 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8209 valuetype_constraint_satisfied = TRUE;
8212 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8213 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8215 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8217 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8219 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8220 valuetype_constraint_satisfied)) {
8225 /*candidate type constraints must be a superset of target's*/
8226 if (tinfo->constraints) {
8227 MonoClass **target_class;
8228 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8229 MonoClass *tc = *target_class;
8232 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8233 * check it's constraints since it satisfy the constraint by itself.
8235 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8238 if (!cinfo->constraints)
8241 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8242 MonoClass *cc = *candidate_class;
8244 if (mono_class_is_assignable_from (tc, cc))
8248 * This happens when we have the following:
8250 * Bar<K> where K : IFace
8251 * Foo<T, U> where T : U where U : IFace
8253 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8256 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8257 if (mono_gparam_is_assignable_from (target, cc))
8261 if (!*candidate_class)
8266 /*candidate itself must have a constraint that satisfy target*/
8267 if (cinfo->constraints) {
8268 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8269 MonoClass *cc = *candidate_class;
8270 if (mono_class_is_assignable_from (target, cc))
8278 * mono_class_is_assignable_from:
8279 * @klass: the class to be assigned to
8280 * @oklass: the source class
8282 * Returns: TRUE if an instance of object oklass can be assigned to an
8283 * instance of object @klass
8286 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8289 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8291 mono_class_init (klass);
8293 if (!oklass->inited)
8294 mono_class_init (oklass);
8296 if (mono_class_has_failure (klass) || mono_class_has_failure (oklass))
8299 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8300 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8302 return mono_gparam_is_assignable_from (klass, oklass);
8305 if (MONO_CLASS_IS_INTERFACE (klass)) {
8306 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8307 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8308 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8312 for (i = 0; constraints [i]; ++i) {
8313 if (mono_class_is_assignable_from (klass, constraints [i]))
8321 /* interface_offsets might not be set for dynamic classes */
8322 if (oklass->ref_info_handle && !oklass->interface_bitmap) {
8324 * oklass might be a generic type parameter but they have
8325 * interface_offsets set.
8327 gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8328 if (!is_ok (&error)) {
8329 mono_error_cleanup (&error);
8334 if (!oklass->interface_bitmap)
8335 /* Happens with generic instances of not-yet created dynamic types */
8337 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8340 if (mono_class_has_variant_generic_params (klass)) {
8342 mono_class_setup_interfaces (oklass, &error);
8343 if (!mono_error_ok (&error)) {
8344 mono_error_cleanup (&error);
8348 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8349 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8350 MonoClass *iface = oklass->interfaces_packed [i];
8352 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8357 } else if (klass->delegate) {
8358 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8360 }else if (klass->rank) {
8361 MonoClass *eclass, *eoclass;
8363 if (oklass->rank != klass->rank)
8366 /* vectors vs. one dimensional arrays */
8367 if (oklass->byval_arg.type != klass->byval_arg.type)
8370 eclass = klass->cast_class;
8371 eoclass = oklass->cast_class;
8374 * a is b does not imply a[] is b[] when a is a valuetype, and
8375 * b is a reference type.
8378 if (eoclass->valuetype) {
8379 if ((eclass == mono_defaults.enum_class) ||
8380 (eclass == mono_defaults.enum_class->parent) ||
8381 (eclass == mono_defaults.object_class))
8385 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8386 } else if (mono_class_is_nullable (klass)) {
8387 if (mono_class_is_nullable (oklass))
8388 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8390 return mono_class_is_assignable_from (klass->cast_class, oklass);
8391 } else if (klass == mono_defaults.object_class)
8394 return mono_class_has_parent (oklass, klass);
8397 /*Check if @oklass is variant compatible with @klass.*/
8399 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8402 MonoType **klass_argv, **oklass_argv;
8403 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8404 MonoGenericContainer *container = klass_gtd->generic_container;
8406 /*Viable candidates are instances of the same generic interface*/
8407 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8410 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8411 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8413 for (j = 0; j < container->type_argc; ++j) {
8414 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8415 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8417 if (param1_class->valuetype != param2_class->valuetype)
8421 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8422 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8424 if (param1_class != param2_class) {
8425 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8426 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8428 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8429 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8437 /*Check if @candidate implements the interface @target*/
8439 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8443 gboolean is_variant = mono_class_has_variant_generic_params (target);
8445 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8446 if (mono_class_is_variant_compatible_slow (target, candidate))
8451 if (candidate == target)
8454 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8455 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8456 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (candidate);
8458 if (tb && tb->interfaces) {
8459 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8460 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8461 MonoClass *iface_class;
8463 /* we can't realize the type here since it can do pretty much anything. */
8466 iface_class = mono_class_from_mono_type (iface->type);
8467 if (iface_class == target)
8469 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8471 if (mono_class_implement_interface_slow (target, iface_class))
8476 /*setup_interfaces don't mono_class_init anything*/
8477 /*FIXME this doesn't handle primitive type arrays.
8478 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8479 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8481 mono_class_setup_interfaces (candidate, &error);
8482 if (!mono_error_ok (&error)) {
8483 mono_error_cleanup (&error);
8487 for (i = 0; i < candidate->interface_count; ++i) {
8488 if (candidate->interfaces [i] == target)
8491 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8494 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8498 candidate = candidate->parent;
8499 } while (candidate);
8505 * Check if @oklass can be assigned to @klass.
8506 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8509 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8511 if (candidate == target)
8513 if (target == mono_defaults.object_class)
8516 if (mono_class_has_parent (candidate, target))
8519 /*If target is not an interface there is no need to check them.*/
8520 if (MONO_CLASS_IS_INTERFACE (target))
8521 return mono_class_implement_interface_slow (target, candidate);
8523 if (target->delegate && mono_class_has_variant_generic_params (target))
8524 return mono_class_is_variant_compatible (target, candidate, FALSE);
8527 MonoClass *eclass, *eoclass;
8529 if (target->rank != candidate->rank)
8532 /* vectors vs. one dimensional arrays */
8533 if (target->byval_arg.type != candidate->byval_arg.type)
8536 eclass = target->cast_class;
8537 eoclass = candidate->cast_class;
8540 * a is b does not imply a[] is b[] when a is a valuetype, and
8541 * b is a reference type.
8544 if (eoclass->valuetype) {
8545 if ((eclass == mono_defaults.enum_class) ||
8546 (eclass == mono_defaults.enum_class->parent) ||
8547 (eclass == mono_defaults.object_class))
8551 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8553 /*FIXME properly handle nullables */
8554 /*FIXME properly handle (M)VAR */
8559 * mono_class_get_cctor:
8560 * @klass: A MonoClass pointer
8562 * Returns: The static constructor of @klass if it exists, NULL otherwise.
8565 mono_class_get_cctor (MonoClass *klass)
8567 MonoCachedClassInfo cached_info;
8569 if (image_is_dynamic (klass->image)) {
8571 * has_cctor is not set for these classes because mono_class_init () is
8574 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8577 if (!klass->has_cctor)
8580 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8582 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8583 if (!mono_error_ok (&error))
8584 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8588 if (klass->generic_class && !klass->methods)
8589 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8591 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8595 * mono_class_get_finalizer:
8596 * @klass: The MonoClass pointer
8598 * Returns: The finalizer method of @klass if it exists, NULL otherwise.
8601 mono_class_get_finalizer (MonoClass *klass)
8603 MonoCachedClassInfo cached_info;
8606 mono_class_init (klass);
8607 if (!mono_class_has_finalizer (klass))
8610 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8612 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8613 if (!mono_error_ok (&error))
8614 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8617 mono_class_setup_vtable (klass);
8618 return klass->vtable [finalize_slot];
8623 * mono_class_needs_cctor_run:
8624 * @klass: the MonoClass pointer
8625 * @caller: a MonoMethod describing the caller
8627 * Determines whenever the class has a static constructor and whenever it
8628 * needs to be called when executing CALLER.
8631 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8635 method = mono_class_get_cctor (klass);
8637 return (method == caller) ? FALSE : TRUE;
8643 * mono_class_array_element_size:
8646 * Returns: The number of bytes an element of type @klass
8647 * uses when stored into an array.
8650 mono_class_array_element_size (MonoClass *klass)
8652 MonoType *type = &klass->byval_arg;
8655 switch (type->type) {
8658 case MONO_TYPE_BOOLEAN:
8662 case MONO_TYPE_CHAR:
8671 case MONO_TYPE_CLASS:
8672 case MONO_TYPE_STRING:
8673 case MONO_TYPE_OBJECT:
8674 case MONO_TYPE_SZARRAY:
8675 case MONO_TYPE_ARRAY:
8676 return sizeof (gpointer);
8681 case MONO_TYPE_VALUETYPE:
8682 if (type->data.klass->enumtype) {
8683 type = mono_class_enum_basetype (type->data.klass);
8684 klass = klass->element_class;
8687 return mono_class_instance_size (klass) - sizeof (MonoObject);
8688 case MONO_TYPE_GENERICINST:
8689 type = &type->data.generic_class->container_class->byval_arg;
8692 case MONO_TYPE_MVAR: {
8695 return mono_type_size (type, &align);
8697 case MONO_TYPE_VOID:
8701 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8707 * mono_array_element_size:
8708 * @ac: pointer to a #MonoArrayClass
8710 * Returns: The size of single array element.
8713 mono_array_element_size (MonoClass *ac)
8715 g_assert (ac->rank);
8716 return ac->sizes.element_size;
8720 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8721 MonoGenericContext *context)
8724 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8725 g_assert (mono_error_ok (&error));
8730 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8731 MonoGenericContext *context, MonoError *error)
8733 mono_error_init (error);
8735 if (image_is_dynamic (image)) {
8736 MonoClass *tmp_handle_class;
8737 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
8739 mono_error_assert_ok (error);
8740 g_assert (tmp_handle_class);
8742 *handle_class = tmp_handle_class;
8744 if (tmp_handle_class == mono_defaults.typehandle_class)
8745 return &((MonoClass*)obj)->byval_arg;
8750 switch (token & 0xff000000) {
8751 case MONO_TOKEN_TYPE_DEF:
8752 case MONO_TOKEN_TYPE_REF:
8753 case MONO_TOKEN_TYPE_SPEC: {
8756 *handle_class = mono_defaults.typehandle_class;
8757 type = mono_type_get_checked (image, token, context, error);
8761 mono_class_init (mono_class_from_mono_type (type));
8762 /* We return a MonoType* as handle */
8765 case MONO_TOKEN_FIELD_DEF: {
8767 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8769 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8773 *handle_class = mono_defaults.fieldhandle_class;
8774 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8778 mono_class_init (klass);
8779 return mono_class_get_field (klass, token);
8781 case MONO_TOKEN_METHOD_DEF:
8782 case MONO_TOKEN_METHOD_SPEC: {
8784 meth = mono_get_method_checked (image, token, NULL, context, error);
8786 *handle_class = mono_defaults.methodhandle_class;
8792 case MONO_TOKEN_MEMBER_REF: {
8793 guint32 cols [MONO_MEMBERREF_SIZE];
8795 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8796 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8797 mono_metadata_decode_blob_size (sig, &sig);
8798 if (*sig == 0x6) { /* it's a field */
8800 MonoClassField *field;
8801 field = mono_field_from_token_checked (image, token, &klass, context, error);
8803 *handle_class = mono_defaults.fieldhandle_class;
8807 meth = mono_get_method_checked (image, token, NULL, context, error);
8809 *handle_class = mono_defaults.methodhandle_class;
8814 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8820 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
8822 MonoClass *handle_class;
8823 mono_error_init (error);
8824 return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
8828 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
8830 return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
8833 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8836 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8838 get_cached_class_info = func;
8842 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8844 if (!get_cached_class_info)
8847 return get_cached_class_info (klass, res);
8851 mono_install_get_class_from_name (MonoGetClassFromName func)
8853 get_class_from_name = func;
8857 * mono_class_get_image:
8859 * Use this method to get the `MonoImage*` where this class came from.
8861 * Returns: The image where this class is defined.
8864 mono_class_get_image (MonoClass *klass)
8866 return klass->image;
8870 * mono_class_get_element_class:
8871 * @klass: the MonoClass to act on
8873 * Use this function to get the element class of an array.
8875 * Returns: The element class of an array.
8878 mono_class_get_element_class (MonoClass *klass)
8880 return klass->element_class;
8884 * mono_class_is_valuetype:
8885 * @klass: the MonoClass to act on
8887 * Use this method to determine if the provided `MonoClass*` represents a value type,
8888 * or a reference type.
8890 * Returns: TRUE if the MonoClass represents a ValueType, FALSE if it represents a reference type.
8893 mono_class_is_valuetype (MonoClass *klass)
8895 return klass->valuetype;
8899 * mono_class_is_enum:
8900 * @klass: the MonoClass to act on
8902 * Use this function to determine if the provided `MonoClass*` represents an enumeration.
8904 * Returns: TRUE if the MonoClass represents an enumeration.
8907 mono_class_is_enum (MonoClass *klass)
8909 return klass->enumtype;
8913 * mono_class_enum_basetype:
8914 * @klass: the MonoClass to act on
8916 * Use this function to get the underlying type for an enumeration value.
8918 * Returns: The underlying type representation for an enumeration.
8921 mono_class_enum_basetype (MonoClass *klass)
8923 if (klass->element_class == klass)
8924 /* SRE or broken types */
8927 return &klass->element_class->byval_arg;
8931 * mono_class_get_parent
8932 * @klass: the MonoClass to act on
8934 * Returns: The parent class for this class.
8937 mono_class_get_parent (MonoClass *klass)
8939 return klass->parent;
8943 * mono_class_get_nesting_type:
8944 * @klass: the MonoClass to act on
8946 * Use this function to obtain the class that the provided `MonoClass*` is nested on.
8948 * If the return is NULL, this indicates that this class is not nested.
8950 * Returns: The container type where this type is nested or NULL if this type is not a nested type.
8953 mono_class_get_nesting_type (MonoClass *klass)
8955 return klass->nested_in;
8959 * mono_class_get_rank:
8960 * @klass: the MonoClass to act on
8962 * Returns: The rank for the array (the number of dimensions).
8965 mono_class_get_rank (MonoClass *klass)
8971 * mono_class_get_flags:
8972 * @klass: the MonoClass to act on
8974 * The type flags from the TypeDef table from the metadata.
8975 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8978 * Returns: The flags from the TypeDef table.
8981 mono_class_get_flags (MonoClass *klass)
8983 return klass->flags;
8987 * mono_class_get_name
8988 * @klass: the MonoClass to act on
8990 * Returns: The name of the class.
8993 mono_class_get_name (MonoClass *klass)
8999 * mono_class_get_namespace:
9000 * @klass: the MonoClass to act on
9002 * Returns: The namespace of the class.
9005 mono_class_get_namespace (MonoClass *klass)
9007 return klass->name_space;
9011 * mono_class_get_type:
9012 * @klass: the MonoClass to act on
9014 * This method returns the internal Type representation for the class.
9016 * Returns: The MonoType from the class.
9019 mono_class_get_type (MonoClass *klass)
9021 return &klass->byval_arg;
9025 * mono_class_get_type_token:
9026 * @klass: the MonoClass to act on
9028 * This method returns type token for the class.
9030 * Returns: The type token for the class.
9033 mono_class_get_type_token (MonoClass *klass)
9035 return klass->type_token;
9039 * mono_class_get_byref_type:
9040 * @klass: the MonoClass to act on
9045 mono_class_get_byref_type (MonoClass *klass)
9047 return &klass->this_arg;
9051 * mono_class_num_fields:
9052 * @klass: the MonoClass to act on
9054 * Returns: The number of static and instance fields in the class.
9057 mono_class_num_fields (MonoClass *klass)
9059 return klass->field.count;
9063 * mono_class_num_methods:
9064 * @klass: the MonoClass to act on
9066 * Returns: The number of methods in the class.
9069 mono_class_num_methods (MonoClass *klass)
9071 return klass->method.count;
9075 * mono_class_num_properties
9076 * @klass: the MonoClass to act on
9078 * Returns: The number of properties in the class.
9081 mono_class_num_properties (MonoClass *klass)
9083 mono_class_setup_properties (klass);
9085 return klass->ext->property.count;
9089 * mono_class_num_events:
9090 * @klass: the MonoClass to act on
9092 * Returns: The number of events in the class.
9095 mono_class_num_events (MonoClass *klass)
9097 mono_class_setup_events (klass);
9099 return klass->ext->event.count;
9103 * mono_class_get_fields:
9104 * @klass: the MonoClass to act on
9106 * This routine is an iterator routine for retrieving the fields in a class.
9108 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9109 * iterate over all of the elements. When no more values are
9110 * available, the return value is NULL.
9112 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
9115 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9117 MonoClassField* field;
9121 mono_class_setup_fields_locking (klass);
9122 if (mono_class_has_failure (klass))
9124 /* start from the first */
9125 if (klass->field.count) {
9126 *iter = &klass->fields [0];
9127 return &klass->fields [0];
9133 field = (MonoClassField *)*iter;
9135 if (field < &klass->fields [klass->field.count]) {
9143 * mono_class_get_methods
9144 * @klass: the MonoClass to act on
9146 * This routine is an iterator routine for retrieving the fields in a class.
9148 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9149 * iterate over all of the elements. When no more values are
9150 * available, the return value is NULL.
9152 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
9155 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9157 MonoMethod** method;
9161 mono_class_setup_methods (klass);
9164 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9165 * FIXME we should better report this error to the caller
9167 if (!klass->methods)
9169 /* start from the first */
9170 if (klass->method.count) {
9171 *iter = &klass->methods [0];
9172 return klass->methods [0];
9178 method = (MonoMethod **)*iter;
9180 if (method < &klass->methods [klass->method.count]) {
9188 * mono_class_get_virtual_methods:
9190 * Iterate over the virtual methods of KLASS.
9192 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9195 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9197 MonoMethod** method;
9200 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9202 mono_class_setup_methods (klass);
9204 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9205 * FIXME we should better report this error to the caller
9207 if (!klass->methods)
9209 /* start from the first */
9210 method = &klass->methods [0];
9212 method = (MonoMethod **)*iter;
9215 while (method < &klass->methods [klass->method.count]) {
9216 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9220 if (method < &klass->methods [klass->method.count]) {
9227 /* Search directly in metadata to avoid calling setup_methods () */
9228 MonoMethod *res = NULL;
9234 start_index = GPOINTER_TO_UINT (*iter);
9237 for (i = start_index; i < klass->method.count; ++i) {
9240 /* klass->method.first points into the methodptr table */
9241 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
9243 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9247 if (i < klass->method.count) {
9249 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9250 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9252 /* Add 1 here so the if (*iter) check fails */
9253 *iter = GUINT_TO_POINTER (i + 1);
9262 * mono_class_get_properties:
9263 * @klass: the MonoClass to act on
9265 * This routine is an iterator routine for retrieving the properties in a class.
9267 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9268 * iterate over all of the elements. When no more values are
9269 * available, the return value is NULL.
9271 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9274 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9276 MonoProperty* property;
9280 mono_class_setup_properties (klass);
9281 /* start from the first */
9282 if (klass->ext->property.count) {
9283 *iter = &klass->ext->properties [0];
9284 return (MonoProperty *)*iter;
9290 property = (MonoProperty *)*iter;
9292 if (property < &klass->ext->properties [klass->ext->property.count]) {
9294 return (MonoProperty *)*iter;
9300 * mono_class_get_events:
9301 * @klass: the MonoClass to act on
9303 * This routine is an iterator routine for retrieving the properties in a class.
9305 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9306 * iterate over all of the elements. When no more values are
9307 * available, the return value is NULL.
9309 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9312 mono_class_get_events (MonoClass* klass, gpointer *iter)
9318 mono_class_setup_events (klass);
9319 /* start from the first */
9320 if (klass->ext->event.count) {
9321 *iter = &klass->ext->events [0];
9322 return (MonoEvent *)*iter;
9328 event = (MonoEvent *)*iter;
9330 if (event < &klass->ext->events [klass->ext->event.count]) {
9332 return (MonoEvent *)*iter;
9338 * mono_class_get_interfaces
9339 * @klass: the MonoClass to act on
9341 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9343 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9344 * iterate over all of the elements. When no more values are
9345 * available, the return value is NULL.
9347 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9350 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9358 mono_class_init (klass);
9359 if (!klass->interfaces_inited) {
9360 mono_class_setup_interfaces (klass, &error);
9361 if (!mono_error_ok (&error)) {
9362 mono_error_cleanup (&error);
9366 /* start from the first */
9367 if (klass->interface_count) {
9368 *iter = &klass->interfaces [0];
9369 return klass->interfaces [0];
9375 iface = (MonoClass **)*iter;
9377 if (iface < &klass->interfaces [klass->interface_count]) {
9385 setup_nested_types (MonoClass *klass)
9388 GList *classes, *nested_classes, *l;
9391 if (klass->nested_classes_inited)
9394 if (!klass->type_token)
9395 klass->nested_classes_inited = TRUE;
9397 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9401 guint32 cols [MONO_NESTED_CLASS_SIZE];
9402 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9403 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9404 if (!mono_error_ok (&error)) {
9405 /*FIXME don't swallow the error message*/
9406 mono_error_cleanup (&error);
9408 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9412 classes = g_list_prepend (classes, nclass);
9414 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9417 mono_class_alloc_ext (klass);
9419 nested_classes = NULL;
9420 for (l = classes; l; l = l->next)
9421 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9422 g_list_free (classes);
9424 mono_image_lock (klass->image);
9426 mono_memory_barrier ();
9427 if (!klass->nested_classes_inited) {
9428 klass->ext->nested_classes = nested_classes;
9429 mono_memory_barrier ();
9430 klass->nested_classes_inited = TRUE;
9433 mono_image_unlock (klass->image);
9437 * mono_class_get_nested_types
9438 * @klass: the MonoClass to act on
9440 * This routine is an iterator routine for retrieving the nested types of a class.
9441 * This works only if @klass is non-generic, or a generic type definition.
9443 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9444 * iterate over all of the elements. When no more values are
9445 * available, the return value is NULL.
9447 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9450 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9456 if (!klass->nested_classes_inited)
9457 setup_nested_types (klass);
9460 /* start from the first */
9461 if (klass->ext && klass->ext->nested_classes) {
9462 *iter = klass->ext->nested_classes;
9463 return (MonoClass *)klass->ext->nested_classes->data;
9465 /* no nested types */
9469 item = (GList *)*iter;
9473 return (MonoClass *)item->data;
9480 * mono_class_is_delegate
9481 * @klass: the MonoClass to act on
9483 * Returns: TRUE if the MonoClass represents a System.Delegate.
9486 mono_class_is_delegate (MonoClass *klass)
9488 return klass->delegate;
9492 * mono_class_implements_interface
9493 * @klass: The MonoClass to act on
9494 * @interface: The interface to check if @klass implements.
9496 * Returns: TRUE if @klass implements @interface.
9499 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9501 return mono_class_is_assignable_from (iface, klass);
9505 * mono_field_get_name:
9506 * @field: the MonoClassField to act on
9508 * Returns: The name of the field.
9511 mono_field_get_name (MonoClassField *field)
9517 * mono_field_get_type:
9518 * @field: the MonoClassField to act on
9520 * Returns: MonoType of the field.
9523 mono_field_get_type (MonoClassField *field)
9526 MonoType *type = mono_field_get_type_checked (field, &error);
9527 if (!mono_error_ok (&error)) {
9528 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9529 mono_error_cleanup (&error);
9536 * mono_field_get_type_checked:
9537 * @field: the MonoClassField to act on
9538 * @error: used to return any erro found while retrieving @field type
9540 * Returns: MonoType of the field.
9543 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9545 mono_error_init (error);
9547 mono_field_resolve_type (field, error);
9552 * mono_field_get_parent:
9553 * @field: the MonoClassField to act on
9555 * Returns: MonoClass where the field was defined.
9558 mono_field_get_parent (MonoClassField *field)
9560 return field->parent;
9564 * mono_field_get_flags;
9565 * @field: the MonoClassField to act on
9567 * The metadata flags for a field are encoded using the
9568 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9570 * Returns: The flags for the field.
9573 mono_field_get_flags (MonoClassField *field)
9576 return mono_field_resolve_flags (field);
9577 return field->type->attrs;
9581 * mono_field_get_offset:
9582 * @field: the MonoClassField to act on
9584 * Returns: The field offset.
9587 mono_field_get_offset (MonoClassField *field)
9589 return field->offset;
9593 mono_field_get_rva (MonoClassField *field)
9597 MonoClass *klass = field->parent;
9598 MonoFieldDefaultValue *field_def_values;
9600 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9602 if (!klass->ext || !klass->ext->field_def_values) {
9603 mono_class_alloc_ext (klass);
9605 field_def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9607 mono_image_lock (klass->image);
9608 if (!klass->ext->field_def_values)
9609 klass->ext->field_def_values = field_def_values;
9610 mono_image_unlock (klass->image);
9613 field_index = mono_field_get_index (field);
9615 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9616 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9618 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9619 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9622 return klass->ext->field_def_values [field_index].data;
9626 * mono_field_get_data:
9627 * @field: the MonoClassField to act on
9629 * Returns: A pointer to the metadata constant value or to the field
9630 * data if it has an RVA flag.
9633 mono_field_get_data (MonoClassField *field)
9635 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9636 MonoTypeEnum def_type;
9638 return mono_class_get_field_default_value (field, &def_type);
9639 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9640 return mono_field_get_rva (field);
9647 * mono_property_get_name:
9648 * @prop: the MonoProperty to act on
9650 * Returns: The name of the property
9653 mono_property_get_name (MonoProperty *prop)
9659 * mono_property_get_set_method
9660 * @prop: the MonoProperty to act on.
9662 * Returns: The setter method of the property (A MonoMethod)
9665 mono_property_get_set_method (MonoProperty *prop)
9671 * mono_property_get_get_method
9672 * @prop: the MonoProperty to act on.
9674 * Returns: The setter method of the property (A MonoMethod)
9677 mono_property_get_get_method (MonoProperty *prop)
9683 * mono_property_get_parent:
9684 * @prop: the MonoProperty to act on.
9686 * Returns: The MonoClass where the property was defined.
9689 mono_property_get_parent (MonoProperty *prop)
9691 return prop->parent;
9695 * mono_property_get_flags:
9696 * @prop: the MonoProperty to act on.
9698 * The metadata flags for a property are encoded using the
9699 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9701 * Returns: The flags for the property.
9704 mono_property_get_flags (MonoProperty *prop)
9710 * mono_event_get_name:
9711 * @event: the MonoEvent to act on
9713 * Returns: The name of the event.
9716 mono_event_get_name (MonoEvent *event)
9722 * mono_event_get_add_method:
9723 * @event: The MonoEvent to act on.
9725 * Returns: The @add' method for the event (a MonoMethod).
9728 mono_event_get_add_method (MonoEvent *event)
9734 * mono_event_get_remove_method:
9735 * @event: The MonoEvent to act on.
9737 * Returns: The @remove method for the event (a MonoMethod).
9740 mono_event_get_remove_method (MonoEvent *event)
9742 return event->remove;
9746 * mono_event_get_raise_method:
9747 * @event: The MonoEvent to act on.
9749 * Returns: The @raise method for the event (a MonoMethod).
9752 mono_event_get_raise_method (MonoEvent *event)
9754 return event->raise;
9758 * mono_event_get_parent:
9759 * @event: the MonoEvent to act on.
9761 * Returns: The MonoClass where the event is defined.
9764 mono_event_get_parent (MonoEvent *event)
9766 return event->parent;
9770 * mono_event_get_flags
9771 * @event: the MonoEvent to act on.
9773 * The metadata flags for an event are encoded using the
9774 * EVENT_* constants. See the tabledefs.h file for details.
9776 * Returns: The flags for the event.
9779 mono_event_get_flags (MonoEvent *event)
9781 return event->attrs;
9785 * mono_class_get_method_from_name:
9786 * @klass: where to look for the method
9787 * @name: name of the method
9788 * @param_count: number of parameters. -1 for any number.
9790 * Obtains a MonoMethod with a given name and number of parameters.
9791 * It only works if there are no multiple signatures for any given method name.
9794 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9796 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9800 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9802 MonoMethod *res = NULL;
9805 /* Search directly in the metadata to avoid calling setup_methods () */
9806 for (i = 0; i < klass->method.count; ++i) {
9808 guint32 cols [MONO_METHOD_SIZE];
9810 MonoMethodSignature *sig;
9812 /* klass->method.first points into the methodptr table */
9813 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9815 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9816 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9818 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9821 if (param_count == -1) {
9825 sig = mono_method_signature_checked (method, &error);
9827 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9830 if (sig->param_count == param_count) {
9841 * mono_class_get_method_from_name_flags:
9842 * @klass: where to look for the method
9843 * @name_space: name of the method
9844 * @param_count: number of parameters. -1 for any number.
9845 * @flags: flags which must be set in the method
9847 * Obtains a MonoMethod with a given name and number of parameters.
9848 * It only works if there are no multiple signatures for any given method name.
9851 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9853 MonoMethod *res = NULL;
9856 mono_class_init (klass);
9858 if (klass->generic_class && !klass->methods) {
9859 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9862 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9863 if (!mono_error_ok (&error))
9864 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9869 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9870 mono_class_setup_methods (klass);
9872 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9873 See mono/tests/array_load_exception.il
9874 FIXME we should better report this error to the caller
9876 if (!klass->methods)
9878 for (i = 0; i < klass->method.count; ++i) {
9879 MonoMethod *method = klass->methods [i];
9881 if (method->name[0] == name [0] &&
9882 !strcmp (name, method->name) &&
9883 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9884 ((method->flags & flags) == flags)) {
9891 res = find_method_in_metadata (klass, name, param_count, flags);
9898 * mono_class_set_failure:
9899 * @klass: class in which the failure was detected
9900 * @ex_type: the kind of exception/error to be thrown (later)
9901 * @ex_data: exception data (specific to each type of exception/error)
9903 * Keep a detected failure informations in the class for later processing.
9904 * Note that only the first failure is kept.
9906 * LOCKING: Acquires the loader lock.
9909 mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error)
9911 g_assert (boxed_error != NULL);
9913 if (mono_class_has_failure (klass))
9916 mono_loader_lock ();
9917 klass->has_failure = 1;
9918 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, boxed_error);
9919 mono_loader_unlock ();
9925 mono_class_has_failure (const MonoClass *klass)
9927 g_assert (klass != NULL);
9928 return klass->has_failure != 0;
9933 * mono_class_set_type_load_failure:
9934 * @klass: class in which the failure was detected
9935 * @fmt: Printf-style error message string.
9937 * Collect detected failure informaion in the class for later processing.
9938 * The error is stored as a MonoErrorBoxed as with mono_error_set_type_load_class ()
9939 * Note that only the first failure is kept.
9941 * Returns FALSE if a failure was already set on the class, or TRUE otherwise.
9943 * LOCKING: Acquires the loader lock.
9946 mono_class_set_type_load_failure (MonoClass *klass, const char * fmt, ...)
9948 MonoError prepare_error;
9951 if (mono_class_has_failure (klass))
9954 mono_error_init (&prepare_error);
9956 va_start (args, fmt);
9957 mono_error_vset_type_load_class (&prepare_error, klass, fmt, args);
9960 MonoErrorBoxed *box = mono_error_box (&prepare_error, klass->image);
9961 mono_error_cleanup (&prepare_error);
9962 return mono_class_set_failure (klass, box);
9966 * mono_class_get_exception_data:
9968 * Return the exception_data property of KLASS.
9970 * LOCKING: Acquires the loader lock.
9973 mono_class_get_exception_data (const MonoClass *klass)
9975 return mono_image_property_lookup (klass->image, (MonoClass*)klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9979 * mono_classes_init:
9981 * Initialize the resources used by this module.
9984 mono_classes_init (void)
9986 mono_os_mutex_init (&classes_mutex);
9988 mono_counters_register ("Inflated methods size",
9989 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9990 mono_counters_register ("Inflated classes",
9991 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9992 mono_counters_register ("Inflated classes size",
9993 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9994 mono_counters_register ("MonoClass size",
9995 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9996 mono_counters_register ("MonoClassExt size",
9997 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
10001 * mono_classes_cleanup:
10003 * Free the resources used by this module.
10006 mono_classes_cleanup (void)
10008 if (global_interface_bitset)
10009 mono_bitset_free (global_interface_bitset);
10010 global_interface_bitset = NULL;
10011 mono_os_mutex_destroy (&classes_mutex);
10015 * mono_class_get_exception_for_failure:
10016 * @klass: class in which the failure was detected
10018 * Return a constructed MonoException than the caller can then throw
10019 * using mono_raise_exception - or NULL if no failure is present (or
10020 * doesn't result in an exception).
10023 mono_class_get_exception_for_failure (MonoClass *klass)
10025 if (!mono_class_has_failure (klass))
10027 MonoError unboxed_error;
10028 mono_error_init (&unboxed_error);
10029 mono_error_set_for_class_failure (&unboxed_error, klass);
10030 return mono_error_convert_to_exception (&unboxed_error);
10034 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
10036 outer_klass = mono_class_get_generic_type_definition (outer_klass);
10037 inner_klass = mono_class_get_generic_type_definition (inner_klass);
10039 if (outer_klass == inner_klass)
10041 inner_klass = inner_klass->nested_in;
10042 } while (inner_klass);
10047 mono_class_get_generic_type_definition (MonoClass *klass)
10049 return klass->generic_class ? klass->generic_class->container_class : klass;
10053 * Check if @klass is a subtype of @parent ignoring generic instantiations.
10055 * Generic instantiations are ignored for all super types of @klass.
10057 * Visibility checks ignoring generic instantiations.
10060 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
10063 klass = mono_class_get_generic_type_definition (klass);
10064 parent = mono_class_get_generic_type_definition (parent);
10065 mono_class_setup_supertypes (klass);
10067 for (i = 0; i < klass->idepth; ++i) {
10068 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
10074 * Subtype can only access parent members with family protection if the site object
10075 * is subclass of Subtype. For example:
10076 * class A { protected int x; }
10078 * void valid_access () {
10082 * void invalid_access () {
10089 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
10091 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
10094 if (context_klass == NULL)
10096 /*if access_klass is not member_klass context_klass must be type compat*/
10097 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10103 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10106 if (accessing == accessed)
10108 if (!accessed || !accessing)
10111 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10112 * anywhere so untrusted friends are not safe to access platform's code internals */
10113 if (mono_security_core_clr_enabled ()) {
10114 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10118 mono_assembly_load_friends (accessed);
10119 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10120 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10121 /* Be conservative with checks */
10122 if (!friend_->name)
10124 if (strcmp (accessing->aname.name, friend_->name))
10126 if (friend_->public_key_token [0]) {
10127 if (!accessing->aname.public_key_token [0])
10129 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10138 * If klass is a generic type or if it is derived from a generic type, return the
10139 * MonoClass of the generic definition
10140 * Returns NULL if not found
10143 get_generic_definition_class (MonoClass *klass)
10146 if (klass->generic_class && klass->generic_class->container_class)
10147 return klass->generic_class->container_class;
10148 klass = klass->parent;
10154 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10157 for (i = 0; i < ginst->type_argc; ++i) {
10158 MonoType *type = ginst->type_argv[i];
10159 switch (type->type) {
10160 case MONO_TYPE_SZARRAY:
10161 if (!can_access_type (access_klass, type->data.klass))
10164 case MONO_TYPE_ARRAY:
10165 if (!can_access_type (access_klass, type->data.array->eklass))
10168 case MONO_TYPE_PTR:
10169 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10172 case MONO_TYPE_CLASS:
10173 case MONO_TYPE_VALUETYPE:
10174 case MONO_TYPE_GENERICINST:
10175 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10185 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10189 if (access_klass == member_klass)
10192 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10195 if (access_klass->element_class && !access_klass->enumtype)
10196 access_klass = access_klass->element_class;
10198 if (member_klass->element_class && !member_klass->enumtype)
10199 member_klass = member_klass->element_class;
10201 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10203 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10206 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
10209 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10212 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10215 /*Non nested type with nested visibility. We just fail it.*/
10216 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10219 switch (access_level) {
10220 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10221 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10223 case TYPE_ATTRIBUTE_PUBLIC:
10226 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10229 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10230 return is_nesting_type (member_klass, access_klass);
10232 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10233 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10235 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10236 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10238 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10239 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10240 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10242 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10243 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10244 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10249 /* FIXME: check visibility of type, too */
10251 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10253 MonoClass *member_generic_def;
10254 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10257 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
10258 access_klass->generic_container) &&
10259 (member_generic_def = get_generic_definition_class (member_klass))) {
10260 MonoClass *access_container;
10262 if (access_klass->generic_container)
10263 access_container = access_klass;
10265 access_container = access_klass->generic_class->container_class;
10267 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10271 /* Partition I 8.5.3.2 */
10272 /* the access level values are the same for fields and methods */
10273 switch (access_level) {
10274 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10275 /* same compilation unit */
10276 return access_klass->image == member_klass->image;
10277 case FIELD_ATTRIBUTE_PRIVATE:
10278 return access_klass == member_klass;
10279 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10280 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10281 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10284 case FIELD_ATTRIBUTE_ASSEMBLY:
10285 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10286 case FIELD_ATTRIBUTE_FAMILY:
10287 if (is_valid_family_access (access_klass, member_klass, context_klass))
10290 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10291 if (is_valid_family_access (access_klass, member_klass, context_klass))
10293 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10294 case FIELD_ATTRIBUTE_PUBLIC:
10301 * mono_method_can_access_field:
10302 * @method: Method that will attempt to access the field
10303 * @field: the field to access
10305 * Used to determine if a method is allowed to access the specified field.
10307 * Returns: TRUE if the given @method is allowed to access the @field while following
10308 * the accessibility rules of the CLI.
10311 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10313 /* FIXME: check all overlapping fields */
10314 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10316 MonoClass *nested = method->klass->nested_in;
10318 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10321 nested = nested->nested_in;
10328 * mono_method_can_access_method:
10329 * @method: Method that will attempt to access the other method
10330 * @called: the method that we want to probe for accessibility.
10332 * Used to determine if the @method is allowed to access the specified @called method.
10334 * Returns: TRUE if the given @method is allowed to invoke the @called while following
10335 * the accessibility rules of the CLI.
10338 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10340 method = mono_method_get_method_definition (method);
10341 called = mono_method_get_method_definition (called);
10342 return mono_method_can_access_method_full (method, called, NULL);
10346 * mono_method_can_access_method_full:
10347 * @method: The caller method
10348 * @called: The called method
10349 * @context_klass: The static type on stack of the owner @called object used
10351 * This function must be used with instance calls, as they have more strict family accessibility.
10352 * It can be used with static methods, but context_klass should be NULL.
10354 * Returns: TRUE if caller have proper visibility and acessibility to @called
10357 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10359 /* Wrappers are except from access checks */
10360 if (method->wrapper_type != MONO_WRAPPER_NONE || called->wrapper_type != MONO_WRAPPER_NONE)
10363 MonoClass *access_class = method->klass;
10364 MonoClass *member_class = called->klass;
10365 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10367 MonoClass *nested = access_class->nested_in;
10369 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10372 nested = nested->nested_in;
10379 can = can_access_type (access_class, member_class);
10381 MonoClass *nested = access_class->nested_in;
10383 can = can_access_type (nested, member_class);
10386 nested = nested->nested_in;
10393 if (called->is_inflated) {
10394 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10395 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10404 * mono_method_can_access_field_full:
10405 * @method: The caller method
10406 * @field: The accessed field
10407 * @context_klass: The static type on stack of the owner @field object used
10409 * This function must be used with instance fields, as they have more strict family accessibility.
10410 * It can be used with static fields, but context_klass should be NULL.
10412 * Returns: TRUE if caller have proper visibility and acessibility to @field
10415 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10417 MonoClass *access_class = method->klass;
10418 MonoClass *member_class = field->parent;
10419 /* FIXME: check all overlapping fields */
10420 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10422 MonoClass *nested = access_class->nested_in;
10424 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10427 nested = nested->nested_in;
10434 can = can_access_type (access_class, member_class);
10436 MonoClass *nested = access_class->nested_in;
10438 can = can_access_type (nested, member_class);
10441 nested = nested->nested_in;
10451 * mono_class_can_access_class:
10452 * @source_class: The source class
10453 * @target_class: The accessed class
10455 * This function returns is @target_class is visible to @source_class
10457 * Returns: TRUE if source have proper visibility and acessibility to target
10460 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10462 return can_access_type (source_class, target_class);
10466 * mono_type_is_valid_enum_basetype:
10467 * @type: The MonoType to check
10469 * Returns: TRUE if the type can be used as the basetype of an enum
10471 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10472 switch (type->type) {
10475 case MONO_TYPE_BOOLEAN:
10478 case MONO_TYPE_CHAR:
10492 * mono_class_is_valid_enum:
10493 * @klass: An enum class to be validated
10495 * This method verify the required properties an enum should have.
10497 * Returns: TRUE if the informed enum class is valid
10499 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10500 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10501 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10503 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10504 MonoClassField * field;
10505 gpointer iter = NULL;
10506 gboolean found_base_field = FALSE;
10508 g_assert (klass->enumtype);
10509 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10510 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10514 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10517 while ((field = mono_class_get_fields (klass, &iter))) {
10518 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10519 if (found_base_field)
10521 found_base_field = TRUE;
10522 if (!mono_type_is_valid_enum_basetype (field->type))
10527 if (!found_base_field)
10530 if (klass->method.count > 0)
10537 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10539 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10543 * mono_class_setup_interface_id:
10545 * Initializes MonoClass::interface_id if required.
10547 * LOCKING: Acquires the loader lock.
10550 mono_class_setup_interface_id (MonoClass *klass)
10552 mono_loader_lock ();
10553 if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10554 klass->interface_id = mono_get_unique_iid (klass);
10555 mono_loader_unlock ();
10559 * mono_class_alloc_ext:
10561 * Allocate klass->ext if not already done.
10564 mono_class_alloc_ext (MonoClass *klass)
10571 ext = (MonoClassExt *)mono_class_alloc0 (klass, sizeof (MonoClassExt));
10572 mono_image_lock (klass->image);
10573 mono_memory_barrier ();
10576 class_ext_size += sizeof (MonoClassExt);
10577 mono_image_unlock (klass->image);
10581 * mono_class_setup_interfaces:
10583 * Initialize klass->interfaces/interfaces_count.
10584 * LOCKING: Acquires the loader lock.
10585 * This function can fail the type.
10588 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10590 int i, interface_count;
10591 MonoClass **interfaces;
10593 mono_error_init (error);
10595 if (klass->interfaces_inited)
10598 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10599 MonoType *args [1];
10601 /* generic IList, ICollection, IEnumerable */
10602 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10603 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10605 args [0] = &klass->element_class->byval_arg;
10606 interfaces [0] = mono_class_bind_generic_parameters (
10607 mono_defaults.generic_ilist_class, 1, args, FALSE);
10608 if (interface_count > 1)
10609 interfaces [1] = mono_class_bind_generic_parameters (
10610 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10611 } else if (klass->generic_class) {
10612 MonoClass *gklass = klass->generic_class->container_class;
10614 mono_class_setup_interfaces (gklass, error);
10615 if (!mono_error_ok (error)) {
10616 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10620 interface_count = gklass->interface_count;
10621 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10622 for (i = 0; i < interface_count; i++) {
10623 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10624 if (!mono_error_ok (error)) {
10625 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10630 interface_count = 0;
10634 mono_image_lock (klass->image);
10636 if (!klass->interfaces_inited) {
10637 klass->interface_count = interface_count;
10638 klass->interfaces = interfaces;
10640 mono_memory_barrier ();
10642 klass->interfaces_inited = TRUE;
10645 mono_image_unlock (klass->image);
10649 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10651 MonoClass *klass = field->parent;
10652 MonoImage *image = klass->image;
10653 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10654 int field_idx = field - klass->fields;
10656 mono_error_init (error);
10659 MonoClassField *gfield = >d->fields [field_idx];
10660 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10661 if (!mono_error_ok (error)) {
10662 mono_class_set_type_load_failure (klass, "Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10665 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10666 if (!mono_error_ok (error)) {
10667 mono_class_set_type_load_failure (klass, "Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10671 guint32 cols [MONO_FIELD_SIZE];
10672 MonoGenericContainer *container = NULL;
10673 int idx = klass->field.first + field_idx;
10675 /*FIXME, in theory we do not lazy load SRE fields*/
10676 g_assert (!image_is_dynamic (image));
10678 if (klass->generic_container) {
10679 container = klass->generic_container;
10681 container = gtd->generic_container;
10682 g_assert (container);
10685 /* klass->field.first and idx points into the fieldptr table */
10686 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10688 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10689 mono_error_set_type_load_class (error, klass, "Could not verify field %s signature", field->name);;
10690 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
10694 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10696 mono_metadata_decode_value (sig, &sig);
10697 /* FIELD signature == 0x06 */
10698 g_assert (*sig == 0x06);
10700 field->type = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10701 if (!field->type) {
10702 mono_class_set_type_load_failure (klass, "Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10708 mono_field_resolve_flags (MonoClassField *field)
10710 MonoClass *klass = field->parent;
10711 MonoImage *image = klass->image;
10712 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10713 int field_idx = field - klass->fields;
10717 MonoClassField *gfield = >d->fields [field_idx];
10718 return mono_field_get_flags (gfield);
10720 int idx = klass->field.first + field_idx;
10722 /*FIXME, in theory we do not lazy load SRE fields*/
10723 g_assert (!image_is_dynamic (image));
10725 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10730 * mono_class_setup_basic_field_info:
10731 * @class: The class to initialize
10733 * Initializes the klass->fields array of fields.
10734 * Aquires the loader lock.
10737 mono_class_setup_basic_field_info_locking (MonoClass *klass)
10739 mono_loader_lock ();
10740 mono_class_setup_basic_field_info (klass);
10741 mono_loader_unlock ();
10745 * mono_class_get_fields_lazy:
10746 * @klass: the MonoClass to act on
10748 * This routine is an iterator routine for retrieving the fields in a class.
10749 * Only minimal information about fields are loaded. Accessors must be used
10750 * for all MonoClassField returned.
10752 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10753 * iterate over all of the elements. When no more values are
10754 * available, the return value is NULL.
10756 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10759 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10761 MonoClassField* field;
10765 mono_class_setup_basic_field_info_locking (klass);
10766 if (!klass->fields)
10768 /* start from the first */
10769 if (klass->field.count) {
10770 *iter = &klass->fields [0];
10771 return (MonoClassField *)*iter;
10777 field = (MonoClassField *)*iter;
10779 if (field < &klass->fields [klass->field.count]) {
10781 return (MonoClassField *)*iter;
10787 mono_class_full_name (MonoClass *klass)
10789 return mono_type_full_name (&klass->byval_arg);
10792 /* Declare all shared lazy type lookup functions */
10793 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, System.Runtime.InteropServices, SafeHandle)