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_setup_fields:
1487 * @class: The class to initialize
1489 * Initializes the klass->fields.
1490 * LOCKING: Assumes the loader lock is held.
1493 mono_class_setup_fields (MonoClass *klass)
1496 MonoImage *m = klass->image;
1498 guint32 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1499 int i, blittable = TRUE;
1500 guint32 real_size = 0;
1501 guint32 packing_size = 0;
1503 gboolean explicit_size;
1504 MonoClassField *field;
1505 MonoGenericContainer *container = NULL;
1506 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
1509 * FIXME: We have a race condition here. It's possible that this function returns
1510 * to its caller with `instance_size` set to `0` instead of the actual size. This
1511 * is not a problem when the function is called recursively on the same class,
1512 * because the size will be initialized by the outer invocation. What follows is a
1513 * description of how it can occur in other cases, too. There it is a problem,
1514 * because it can lead to the GC being asked to allocate an object of size `0`,
1515 * which SGen chokes on. The race condition is triggered infrequently by
1516 * `tests/sgen-suspend.cs`.
1518 * This function is called for a class whenever one of its subclasses is inited.
1519 * For example, it's called for every subclass of Object. What it does is this:
1521 * if (klass->setup_fields_called)
1524 * klass->instance_size = 0;
1526 * klass->setup_fields_called = 1;
1527 * ... critical point
1528 * klass->instance_size = actual_instance_size;
1530 * The last two steps are sometimes reversed, but that only changes the way in which
1531 * the race condition works.
1533 * Assume thread A goes through this function and makes it to the critical point.
1534 * Now thread B runs the function and, since `setup_fields_called` is set, returns
1535 * immediately, but `instance_size` is incorrect.
1537 * The other case looks like this:
1539 * if (klass->setup_fields_called)
1541 * ... critical point X
1542 * klass->instance_size = 0;
1543 * ... critical point Y
1544 * klass->instance_size = actual_instance_size;
1546 * klass->setup_fields_called = 1;
1548 * Assume thread A goes through the function and makes it to critical point X. Now
1549 * thread B runs through the whole of the function, returning, assuming
1550 * `instance_size` is set. At that point thread A gets to run and makes it to
1551 * critical point Y, at which time `instance_size` is `0` again, invalidating thread
1554 if (klass->setup_fields_called)
1557 if (klass->generic_class && image_is_dynamic (klass->generic_class->container_class->image) && !klass->generic_class->container_class->wastypebuilder) {
1559 * This happens when a generic instance of an unfinished generic typebuilder
1560 * is used as an element type for creating an array type. We can't initialize
1561 * the fields of this class using the fields of gklass, since gklass is not
1562 * finished yet, fields could be added to it later.
1567 mono_class_setup_basic_field_info (klass);
1568 top = klass->field.count;
1571 mono_class_setup_fields (gtd);
1572 if (mono_class_has_failure (gtd)) {
1573 mono_class_set_type_load_failure (klass, "");
1580 klass->sizes.class_size = 0;
1582 if (klass->parent) {
1583 /* For generic instances, klass->parent might not have been initialized */
1584 mono_class_init (klass->parent);
1585 if (!klass->parent->size_inited) {
1586 mono_class_setup_fields (klass->parent);
1587 if (mono_class_has_failure (klass->parent)) {
1588 mono_class_set_type_load_failure (klass, "");
1592 instance_size += klass->parent->instance_size;
1593 klass->min_align = klass->parent->min_align;
1594 /* we use |= since it may have been set already */
1595 klass->has_references |= klass->parent->has_references;
1596 blittable = klass->parent->blittable;
1598 instance_size = sizeof (MonoObject);
1599 klass->min_align = 1;
1602 /* We can't really enable 16 bytes alignment until the GC supports it.
1603 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1604 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1605 Bug #506144 is an example of this issue.
1607 if (klass->simd_type)
1608 klass->min_align = 16;
1610 /* Get the real size */
1611 explicit_size = mono_metadata_packing_from_typedef (klass->image, klass->type_token, &packing_size, &real_size);
1613 if (explicit_size) {
1614 if ((packing_size & 0xffffff00) != 0) {
1615 mono_class_set_type_load_failure (klass, "Could not load struct '%s' with packing size %d >= 256", klass->name, packing_size);
1618 klass->packing_size = packing_size;
1619 real_size += instance_size;
1623 if (explicit_size && real_size) {
1624 instance_size = MAX (real_size, instance_size);
1626 klass->blittable = blittable;
1627 if (!klass->instance_size)
1628 klass->instance_size = instance_size;
1629 mono_memory_barrier ();
1630 klass->size_inited = 1;
1631 klass->fields_inited = 1;
1632 klass->setup_fields_called = 1;
1636 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(mono_is_corlib_image (klass->image) && !strcmp (klass->name_space, "System") && !strcmp (klass->name, "ValueType")))
1639 /* Prevent infinite loops if the class references itself */
1640 klass->setup_fields_called = 1;
1642 if (klass->generic_container) {
1643 container = klass->generic_container;
1645 container = gtd->generic_container;
1646 g_assert (container);
1650 * Fetch all the field information.
1652 for (i = 0; i < top; i++){
1653 int idx = klass->field.first + i;
1654 field = &klass->fields [i];
1656 field->parent = klass;
1659 mono_field_resolve_type (field, &error);
1660 if (!mono_error_ok (&error)) {
1661 /*mono_field_resolve_type already failed class*/
1662 mono_error_cleanup (&error);
1666 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(klass), field->name);
1667 g_assert (field->type);
1670 if (mono_field_is_deleted (field))
1673 MonoClassField *gfield = >d->fields [i];
1674 field->offset = gfield->offset;
1676 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1678 mono_metadata_field_info (m, idx, &offset, NULL, NULL);
1679 field->offset = offset;
1681 if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1682 mono_class_set_type_load_failure (klass, "Missing field layout info for %s", field->name);
1685 if (field->offset < -1) { /*-1 is used to encode special static fields */
1686 mono_class_set_type_load_failure (klass, "Invalid negative field offset %d for %s", field->offset, field->name);
1689 if (klass->generic_container) {
1690 mono_class_set_type_load_failure (klass, "Generic class cannot have explicit layout.");
1696 /* Only do these checks if we still think this type is blittable */
1697 if (blittable && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1698 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1701 MonoClass *field_class = mono_class_from_mono_type (field->type);
1703 mono_class_setup_fields (field_class);
1704 if (mono_class_has_failure (field_class)) {
1705 mono_class_set_type_load_failure (klass, "");
1709 if (!field_class || !field_class->blittable)
1714 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1715 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
1716 blittable = klass->element_class->blittable;
1719 if (mono_type_has_exceptions (field->type)) {
1720 char *class_name = mono_type_get_full_name (klass);
1721 char *type_name = mono_type_full_name (field->type);
1723 mono_class_set_type_load_failure (klass, "");
1724 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1725 g_free (class_name);
1729 /* The def_value of fields is compute lazily during vtable creation */
1732 if (klass == mono_defaults.string_class)
1735 klass->blittable = blittable;
1737 if (klass->enumtype && !mono_class_enum_basetype (klass)) {
1738 mono_class_set_type_load_failure (klass, "");
1741 if (explicit_size && real_size) {
1742 instance_size = MAX (real_size, instance_size);
1745 if (mono_class_has_failure (klass))
1747 mono_class_layout_fields (klass, instance_size);
1749 /*valuetypes can't be neither bigger than 1Mb or empty. */
1750 if (klass->valuetype && (klass->instance_size <= 0 || klass->instance_size > (0x100000 + sizeof (MonoObject))))
1751 mono_class_set_type_load_failure (klass, "");
1753 mono_memory_barrier ();
1754 klass->fields_inited = 1;
1758 * mono_class_setup_fields_locking:
1759 * @class: The class to initialize
1761 * Initializes the klass->fields array of fields.
1762 * Aquires the loader lock.
1765 mono_class_setup_fields_locking (MonoClass *klass)
1767 /* This can be checked without locks */
1768 if (klass->fields_inited)
1770 mono_loader_lock ();
1771 mono_class_setup_fields (klass);
1772 mono_loader_unlock ();
1776 * mono_class_has_references:
1778 * Returns whenever @klass->has_references is set, initializing it if needed.
1779 * Aquires the loader lock.
1782 mono_class_has_references (MonoClass *klass)
1784 if (klass->init_pending) {
1785 /* Be conservative */
1788 mono_class_init (klass);
1790 return klass->has_references;
1795 * mono_type_get_basic_type_from_generic:
1798 * Returns a closed type corresponding to the possibly open type
1802 mono_type_get_basic_type_from_generic (MonoType *type)
1804 /* When we do generic sharing we let type variables stand for reference/primitive types. */
1805 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) &&
1806 (!type->data.generic_param->gshared_constraint || type->data.generic_param->gshared_constraint->type == MONO_TYPE_OBJECT))
1807 return &mono_defaults.object_class->byval_arg;
1812 type_has_references (MonoClass *klass, MonoType *ftype)
1814 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)))))
1816 if (!ftype->byref && (ftype->type == MONO_TYPE_VAR || ftype->type == MONO_TYPE_MVAR)) {
1817 MonoGenericParam *gparam = ftype->data.generic_param;
1819 if (gparam->gshared_constraint)
1820 return mono_class_has_references (mono_class_from_mono_type (gparam->gshared_constraint));
1826 * mono_class_layout_fields:
1828 * @instance_size: base instance size
1830 * Compute the placement of fields inside an object or struct, according to
1831 * the layout rules and set the following fields in @class:
1832 * - has_references (if the class contains instance references firled or structs that contain references)
1833 * - has_static_refs (same, but for static fields)
1834 * - instance_size (size of the object in memory)
1835 * - class_size (size needed for the static fields)
1836 * - size_inited (flag set when the instance_size is set)
1838 * LOCKING: this is supposed to be called with the loader lock held.
1841 mono_class_layout_fields (MonoClass *klass, int instance_size)
1844 const int top = klass->field.count;
1845 guint32 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1846 guint32 pass, passes, real_size;
1847 gboolean gc_aware_layout = FALSE;
1848 gboolean has_static_fields = FALSE;
1849 MonoClassField *field;
1852 * When we do generic sharing we need to have layout
1853 * information for open generic classes (either with a generic
1854 * context containing type variables or with a generic
1855 * container), so we don't return in that case anymore.
1859 * Enable GC aware auto layout: in this mode, reference
1860 * fields are grouped together inside objects, increasing collector
1862 * Requires that all classes whose layout is known to native code be annotated
1863 * with [StructLayout (LayoutKind.Sequential)]
1864 * Value types have gc_aware_layout disabled by default, as per
1865 * what the default is for other runtimes.
1867 /* corlib is missing [StructLayout] directives in many places */
1868 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1869 if (!klass->valuetype)
1870 gc_aware_layout = TRUE;
1873 /* Compute klass->has_references */
1875 * Process non-static fields first, since static fields might recursively
1876 * refer to the class itself.
1878 for (i = 0; i < top; i++) {
1881 field = &klass->fields [i];
1883 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1884 ftype = mono_type_get_underlying_type (field->type);
1885 ftype = mono_type_get_basic_type_from_generic (ftype);
1886 if (type_has_references (klass, ftype))
1887 klass->has_references = TRUE;
1891 for (i = 0; i < top; i++) {
1894 field = &klass->fields [i];
1896 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1897 ftype = mono_type_get_underlying_type (field->type);
1898 ftype = mono_type_get_basic_type_from_generic (ftype);
1899 if (type_has_references (klass, ftype))
1900 klass->has_static_refs = TRUE;
1904 for (i = 0; i < top; i++) {
1907 field = &klass->fields [i];
1909 ftype = mono_type_get_underlying_type (field->type);
1910 ftype = mono_type_get_basic_type_from_generic (ftype);
1911 if (type_has_references (klass, ftype)) {
1912 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1913 klass->has_static_refs = TRUE;
1915 klass->has_references = TRUE;
1920 * Compute field layout and total size (not considering static fields)
1923 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1924 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1926 if (gc_aware_layout)
1931 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1934 if (klass->parent) {
1935 mono_class_setup_fields (klass->parent);
1936 if (mono_class_has_failure (klass->parent)) {
1937 mono_class_set_type_load_failure (klass, "");
1940 real_size = klass->parent->instance_size;
1942 real_size = sizeof (MonoObject);
1945 for (pass = 0; pass < passes; ++pass) {
1946 for (i = 0; i < top; i++){
1951 field = &klass->fields [i];
1953 if (mono_field_is_deleted (field))
1955 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1958 ftype = mono_type_get_underlying_type (field->type);
1959 ftype = mono_type_get_basic_type_from_generic (ftype);
1960 if (gc_aware_layout) {
1961 if (type_has_references (klass, ftype)) {
1970 if ((top == 1) && (klass->instance_size == sizeof (MonoObject)) &&
1971 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1972 /* This field is a hack inserted by MCS to empty structures */
1976 size = mono_type_size (field->type, &align);
1978 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1979 align = klass->packing_size ? MIN (klass->packing_size, align): align;
1980 /* if the field has managed references, we need to force-align it
1983 if (type_has_references (klass, ftype))
1984 align = MAX (align, sizeof (gpointer));
1986 klass->min_align = MAX (align, klass->min_align);
1987 field->offset = real_size;
1989 field->offset += align - 1;
1990 field->offset &= ~(align - 1);
1992 /*TypeBuilders produce all sort of weird things*/
1993 g_assert (image_is_dynamic (klass->image) || field->offset > 0);
1994 real_size = field->offset + size;
1997 instance_size = MAX (real_size, instance_size);
1999 if (instance_size & (klass->min_align - 1)) {
2000 instance_size += klass->min_align - 1;
2001 instance_size &= ~(klass->min_align - 1);
2005 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
2009 for (i = 0; i < top; i++) {
2014 field = &klass->fields [i];
2017 * There must be info about all the fields in a type if it
2018 * uses explicit layout.
2020 if (mono_field_is_deleted (field))
2022 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2025 size = mono_type_size (field->type, &align);
2026 align = klass->packing_size ? MIN (klass->packing_size, align): align;
2027 klass->min_align = MAX (align, klass->min_align);
2030 * When we get here, field->offset is already set by the
2031 * loader (for either runtime fields or fields loaded from metadata).
2032 * The offset is from the start of the object: this works for both
2033 * classes and valuetypes.
2035 field->offset += sizeof (MonoObject);
2036 ftype = mono_type_get_underlying_type (field->type);
2037 ftype = mono_type_get_basic_type_from_generic (ftype);
2038 if (type_has_references (klass, ftype)) {
2039 if (field->offset % sizeof (gpointer)) {
2040 mono_class_set_type_load_failure (klass, "");
2047 real_size = MAX (real_size, size + field->offset);
2050 if (klass->has_references) {
2051 ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
2053 /* Check for overlapping reference and non-reference fields */
2054 for (i = 0; i < top; i++) {
2057 field = &klass->fields [i];
2059 if (mono_field_is_deleted (field))
2061 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2063 ftype = mono_type_get_underlying_type (field->type);
2064 if (MONO_TYPE_IS_REFERENCE (ftype))
2065 ref_bitmap [field->offset / sizeof (gpointer)] = 1;
2067 for (i = 0; i < top; i++) {
2068 field = &klass->fields [i];
2070 if (mono_field_is_deleted (field))
2072 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2075 // FIXME: Too much code does this
2077 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field->offset / sizeof (gpointer)]) {
2078 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);
2082 g_free (ref_bitmap);
2085 instance_size = MAX (real_size, instance_size);
2086 if (instance_size & (klass->min_align - 1)) {
2087 instance_size += klass->min_align - 1;
2088 instance_size &= ~(klass->min_align - 1);
2094 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2096 * This leads to all kinds of problems with nested structs, so only
2097 * enable it when a MONO_DEBUG property is set.
2099 * For small structs, set min_align to at least the struct size to improve
2100 * performance, and since the JIT memset/memcpy code assumes this and generates
2101 * unaligned accesses otherwise. See #78990 for a testcase.
2103 if (mono_align_small_structs) {
2104 if (instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2105 klass->min_align = MAX (klass->min_align, instance_size - sizeof (MonoObject));
2109 if (klass->instance_size && !klass->image->dynamic) {
2110 /* Might be already set using cached info */
2111 g_assert (klass->instance_size == instance_size);
2113 klass->instance_size = instance_size;
2115 mono_memory_barrier ();
2116 klass->size_inited = 1;
2119 * Compute static field layout and size
2121 for (i = 0; i < top; i++){
2125 field = &klass->fields [i];
2127 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2129 if (mono_field_is_deleted (field))
2132 if (mono_type_has_exceptions (field->type)) {
2133 mono_class_set_type_load_failure (klass, "");
2137 has_static_fields = TRUE;
2139 size = mono_type_size (field->type, &align);
2140 field->offset = klass->sizes.class_size;
2141 /*align is always non-zero here*/
2142 field->offset += align - 1;
2143 field->offset &= ~(align - 1);
2144 klass->sizes.class_size = field->offset + size;
2147 if (has_static_fields && klass->sizes.class_size == 0)
2148 /* Simplify code which depends on class_size != 0 if the class has static fields */
2149 klass->sizes.class_size = 8;
2153 create_array_method (MonoClass *klass, const char *name, MonoMethodSignature *sig)
2157 method = (MonoMethod *) mono_image_alloc0 (klass->image, sizeof (MonoMethodPInvoke));
2158 method->klass = klass;
2159 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2160 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2161 method->signature = sig;
2162 method->name = name;
2165 if (name [0] == '.') {
2166 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2168 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2174 * mono_class_setup_methods:
2177 * Initializes the 'methods' array in CLASS.
2178 * Calling this method should be avoided if possible since it allocates a lot
2179 * of long-living MonoMethod structures.
2180 * Methods belonging to an interface are assigned a sequential slot starting
2183 * On failure this function sets klass->has_failure and stores a MonoErrorBoxed with details
2186 mono_class_setup_methods (MonoClass *klass)
2189 MonoMethod **methods;
2194 if (klass->generic_class) {
2196 MonoClass *gklass = klass->generic_class->container_class;
2198 mono_class_init (gklass);
2199 if (!mono_class_has_failure (gklass))
2200 mono_class_setup_methods (gklass);
2201 if (mono_class_has_failure (gklass)) {
2202 /* FIXME make exception_data less opaque so it's possible to dup it here */
2203 mono_class_set_type_load_failure (klass, "Generic type definition failed to load");
2207 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2208 count = gklass->method.count;
2209 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * (count + 1));
2211 for (i = 0; i < count; i++) {
2212 methods [i] = mono_class_inflate_generic_method_full_checked (
2213 gklass->methods [i], klass, mono_class_get_context (klass), &error);
2214 if (!mono_error_ok (&error)) {
2215 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2216 mono_class_set_type_load_failure (klass, "Could not inflate method %s due to %s", method, mono_error_get_message (&error));
2219 mono_error_cleanup (&error);
2223 } else if (klass->rank) {
2225 MonoMethod *amethod;
2226 MonoMethodSignature *sig;
2227 int count_generic = 0, first_generic = 0;
2229 gboolean jagged_ctor = FALSE;
2231 count = 3 + (klass->rank > 1? 2: 1);
2233 mono_class_setup_interfaces (klass, &error);
2234 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2236 if (klass->rank == 1 && klass->element_class->rank) {
2238 klass->method.count ++;
2241 if (klass->interface_count) {
2242 count_generic = generic_array_methods (klass);
2243 first_generic = count;
2244 count += klass->interface_count * count_generic;
2247 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * count);
2249 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2250 sig->ret = &mono_defaults.void_class->byval_arg;
2251 sig->pinvoke = TRUE;
2252 sig->hasthis = TRUE;
2253 for (i = 0; i < klass->rank; ++i)
2254 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2256 amethod = create_array_method (klass, ".ctor", sig);
2257 methods [method_num++] = amethod;
2258 if (klass->rank > 1) {
2259 sig = mono_metadata_signature_alloc (klass->image, klass->rank * 2);
2260 sig->ret = &mono_defaults.void_class->byval_arg;
2261 sig->pinvoke = TRUE;
2262 sig->hasthis = TRUE;
2263 for (i = 0; i < klass->rank * 2; ++i)
2264 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2266 amethod = create_array_method (klass, ".ctor", sig);
2267 methods [method_num++] = amethod;
2271 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2272 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2273 sig->ret = &mono_defaults.void_class->byval_arg;
2274 sig->pinvoke = TRUE;
2275 sig->hasthis = TRUE;
2276 for (i = 0; i < klass->rank + 1; ++i)
2277 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2278 amethod = create_array_method (klass, ".ctor", sig);
2279 methods [method_num++] = amethod;
2282 /* element Get (idx11, [idx2, ...]) */
2283 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2284 sig->ret = &klass->element_class->byval_arg;
2285 sig->pinvoke = TRUE;
2286 sig->hasthis = TRUE;
2287 for (i = 0; i < klass->rank; ++i)
2288 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2289 amethod = create_array_method (klass, "Get", sig);
2290 methods [method_num++] = amethod;
2291 /* element& Address (idx11, [idx2, ...]) */
2292 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2293 sig->ret = &klass->element_class->this_arg;
2294 sig->pinvoke = TRUE;
2295 sig->hasthis = TRUE;
2296 for (i = 0; i < klass->rank; ++i)
2297 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2298 amethod = create_array_method (klass, "Address", sig);
2299 methods [method_num++] = amethod;
2300 /* void Set (idx11, [idx2, ...], element) */
2301 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2302 sig->ret = &mono_defaults.void_class->byval_arg;
2303 sig->pinvoke = TRUE;
2304 sig->hasthis = TRUE;
2305 for (i = 0; i < klass->rank; ++i)
2306 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2307 sig->params [i] = &klass->element_class->byval_arg;
2308 amethod = create_array_method (klass, "Set", sig);
2309 methods [method_num++] = amethod;
2311 for (i = 0; i < klass->interface_count; i++)
2312 setup_generic_array_ifaces (klass, klass->interfaces [i], methods, first_generic + i * count_generic);
2316 count = klass->method.count;
2317 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * count);
2318 for (i = 0; i < count; ++i) {
2319 int idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_METHOD, klass->method.first + i + 1);
2320 methods [i] = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | idx, klass, NULL, &error);
2322 mono_class_set_type_load_failure (klass, "Could not load method %d due to %s", i, mono_error_get_message (&error));
2323 mono_error_cleanup (&error);
2328 if (MONO_CLASS_IS_INTERFACE (klass)) {
2330 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2331 for (i = 0; i < count; ++i) {
2332 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2333 methods [i]->slot = slot++;
2337 mono_image_lock (klass->image);
2339 if (!klass->methods) {
2340 klass->method.count = count;
2342 /* Needed because of the double-checking locking pattern */
2343 mono_memory_barrier ();
2345 klass->methods = methods;
2348 mono_image_unlock (klass->image);
2352 * mono_class_get_method_by_index:
2354 * Returns klass->methods [index], initializing klass->methods if neccesary.
2356 * LOCKING: Acquires the loader lock.
2359 mono_class_get_method_by_index (MonoClass *klass, int index)
2362 /* Avoid calling setup_methods () if possible */
2363 if (klass->generic_class && !klass->methods) {
2364 MonoClass *gklass = klass->generic_class->container_class;
2367 m = mono_class_inflate_generic_method_full_checked (
2368 gklass->methods [index], klass, mono_class_get_context (klass), &error);
2369 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2371 * If setup_methods () is called later for this class, no duplicates are created,
2372 * since inflate_generic_method guarantees that only one instance of a method
2373 * is created for each context.
2376 mono_class_setup_methods (klass);
2377 g_assert (m == klass->methods [index]);
2381 mono_class_setup_methods (klass);
2382 if (mono_class_has_failure (klass)) /*FIXME do proper error handling*/
2384 g_assert (index >= 0 && index < klass->method.count);
2385 return klass->methods [index];
2390 * mono_class_get_inflated_method:
2392 * Given an inflated class CLASS and a method METHOD which should be a method of
2393 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2396 mono_class_get_inflated_method (MonoClass *klass, MonoMethod *method)
2398 MonoClass *gklass = klass->generic_class->container_class;
2401 g_assert (method->klass == gklass);
2403 mono_class_setup_methods (gklass);
2404 g_assert (!mono_class_has_failure (gklass)); /*FIXME do proper error handling*/
2406 for (i = 0; i < gklass->method.count; ++i) {
2407 if (gklass->methods [i] == method) {
2408 if (klass->methods) {
2409 return klass->methods [i];
2412 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], klass, mono_class_get_context (klass), &error);
2413 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2423 * mono_class_get_vtable_entry:
2425 * Returns klass->vtable [offset], computing it if neccesary. Returns NULL on failure.
2426 * LOCKING: Acquires the loader lock.
2429 mono_class_get_vtable_entry (MonoClass *klass, int offset)
2433 if (klass->rank == 1) {
2435 * szarrays do not overwrite any methods of Array, so we can avoid
2436 * initializing their vtables in some cases.
2438 mono_class_setup_vtable (klass->parent);
2439 if (offset < klass->parent->vtable_size)
2440 return klass->parent->vtable [offset];
2443 if (klass->generic_class) {
2445 MonoClass *gklass = klass->generic_class->container_class;
2446 mono_class_setup_vtable (gklass);
2447 m = gklass->vtable [offset];
2449 m = mono_class_inflate_generic_method_full_checked (m, klass, mono_class_get_context (klass), &error);
2450 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2452 mono_class_setup_vtable (klass);
2453 if (mono_class_has_failure (klass))
2455 m = klass->vtable [offset];
2462 * mono_class_get_vtable_size:
2464 * Return the vtable size for KLASS.
2467 mono_class_get_vtable_size (MonoClass *klass)
2469 mono_class_setup_vtable (klass);
2471 return klass->vtable_size;
2475 * mono_class_setup_properties:
2477 * Initialize klass->ext.property and klass->ext.properties.
2479 * This method can fail the class.
2482 mono_class_setup_properties (MonoClass *klass)
2484 guint startm, endm, i, j;
2485 guint32 cols [MONO_PROPERTY_SIZE];
2486 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2487 MonoProperty *properties;
2491 if (klass->ext && klass->ext->properties)
2494 if (klass->generic_class) {
2495 MonoClass *gklass = klass->generic_class->container_class;
2497 mono_class_init (gklass);
2498 mono_class_setup_properties (gklass);
2499 if (mono_class_has_failure (gklass)) {
2500 mono_class_set_type_load_failure (klass, "Generic type definition failed to load");
2504 properties = mono_class_new0 (klass, MonoProperty, gklass->ext->property.count + 1);
2506 for (i = 0; i < gklass->ext->property.count; i++) {
2508 MonoProperty *prop = &properties [i];
2510 *prop = gklass->ext->properties [i];
2513 prop->get = mono_class_inflate_generic_method_full_checked (
2514 prop->get, klass, mono_class_get_context (klass), &error);
2516 prop->set = mono_class_inflate_generic_method_full_checked (
2517 prop->set, klass, mono_class_get_context (klass), &error);
2519 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2520 prop->parent = klass;
2523 first = gklass->ext->property.first;
2524 count = gklass->ext->property.count;
2526 first = mono_metadata_properties_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2527 count = last - first;
2530 mono_class_setup_methods (klass);
2531 if (mono_class_has_failure (klass))
2535 properties = (MonoProperty *)mono_class_alloc0 (klass, sizeof (MonoProperty) * count);
2536 for (i = first; i < last; ++i) {
2537 mono_metadata_decode_table_row (klass->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2538 properties [i - first].parent = klass;
2539 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2540 properties [i - first].name = mono_metadata_string_heap (klass->image, cols [MONO_PROPERTY_NAME]);
2542 startm = mono_metadata_methods_from_property (klass->image, i, &endm);
2543 for (j = startm; j < endm; ++j) {
2546 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2548 if (klass->image->uncompressed_metadata) {
2550 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2551 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2552 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2554 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - klass->method.first];
2557 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2558 case METHOD_SEMANTIC_SETTER:
2559 properties [i - first].set = method;
2561 case METHOD_SEMANTIC_GETTER:
2562 properties [i - first].get = method;
2571 mono_class_alloc_ext (klass);
2573 mono_image_lock (klass->image);
2575 if (klass->ext->properties) {
2576 /* We leak 'properties' which was allocated from the image mempool */
2577 mono_image_unlock (klass->image);
2581 klass->ext->property.first = first;
2582 klass->ext->property.count = count;
2584 /* Flush any pending writes as we do double checked locking on klass->ext->properties */
2585 mono_memory_barrier ();
2587 /* Leave this assignment as the last op in the function */
2588 klass->ext->properties = properties;
2590 mono_image_unlock (klass->image);
2594 inflate_method_listz (MonoMethod **methods, MonoClass *klass, MonoGenericContext *context)
2596 MonoMethod **om, **retval;
2599 for (om = methods, count = 0; *om; ++om, ++count)
2602 retval = g_new0 (MonoMethod*, count + 1);
2604 for (om = methods, count = 0; *om; ++om, ++count) {
2606 retval [count] = mono_class_inflate_generic_method_full_checked (*om, klass, context, &error);
2607 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2613 /*This method can fail the class.*/
2615 mono_class_setup_events (MonoClass *klass)
2618 guint startm, endm, i, j;
2619 guint32 cols [MONO_EVENT_SIZE];
2620 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2624 if (klass->ext && klass->ext->events)
2627 if (klass->generic_class) {
2628 MonoClass *gklass = klass->generic_class->container_class;
2629 MonoGenericContext *context = NULL;
2631 mono_class_setup_events (gklass);
2632 if (mono_class_has_failure (gklass)) {
2633 mono_class_set_type_load_failure (klass, "Generic type definition failed to load");
2637 first = gklass->ext->event.first;
2638 count = gklass->ext->event.count;
2640 events = mono_class_new0 (klass, MonoEvent, count);
2643 context = mono_class_get_context (klass);
2645 for (i = 0; i < count; i++) {
2647 MonoEvent *event = &events [i];
2648 MonoEvent *gevent = &gklass->ext->events [i];
2650 mono_error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2652 event->parent = klass;
2653 event->name = gevent->name;
2654 event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, klass, context, &error) : NULL;
2655 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2656 event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, klass, context, &error) : NULL;
2657 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2658 event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, klass, context, &error) : NULL;
2659 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2661 #ifndef MONO_SMALL_CONFIG
2662 event->other = gevent->other ? inflate_method_listz (gevent->other, klass, context) : NULL;
2664 event->attrs = gevent->attrs;
2667 first = mono_metadata_events_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2668 count = last - first;
2671 mono_class_setup_methods (klass);
2672 if (mono_class_has_failure (klass)) {
2673 mono_class_set_type_load_failure (klass, "Generic type definition failed to load");
2678 events = (MonoEvent *)mono_class_alloc0 (klass, sizeof (MonoEvent) * count);
2679 for (i = first; i < last; ++i) {
2680 MonoEvent *event = &events [i - first];
2682 mono_metadata_decode_table_row (klass->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2683 event->parent = klass;
2684 event->attrs = cols [MONO_EVENT_FLAGS];
2685 event->name = mono_metadata_string_heap (klass->image, cols [MONO_EVENT_NAME]);
2687 startm = mono_metadata_methods_from_event (klass->image, i, &endm);
2688 for (j = startm; j < endm; ++j) {
2691 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2693 if (klass->image->uncompressed_metadata) {
2695 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2696 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2697 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2699 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - klass->method.first];
2702 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2703 case METHOD_SEMANTIC_ADD_ON:
2704 event->add = method;
2706 case METHOD_SEMANTIC_REMOVE_ON:
2707 event->remove = method;
2709 case METHOD_SEMANTIC_FIRE:
2710 event->raise = method;
2712 case METHOD_SEMANTIC_OTHER: {
2713 #ifndef MONO_SMALL_CONFIG
2716 if (event->other == NULL) {
2717 event->other = g_new0 (MonoMethod*, 2);
2719 while (event->other [n])
2721 event->other = (MonoMethod **)g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2723 event->other [n] = method;
2724 /* NULL terminated */
2725 event->other [n + 1] = NULL;
2736 mono_class_alloc_ext (klass);
2738 mono_image_lock (klass->image);
2740 if (klass->ext->events) {
2741 mono_image_unlock (klass->image);
2745 klass->ext->event.first = first;
2746 klass->ext->event.count = count;
2748 /* Flush any pending writes as we do double checked locking on klass->ext.events */
2749 mono_memory_barrier ();
2751 /* Leave this assignment as the last op in the function */
2752 klass->ext->events = events;
2754 mono_image_unlock (klass->image);
2758 * Global pool of interface IDs, represented as a bitset.
2759 * LOCKING: Protected by the classes lock.
2761 static MonoBitSet *global_interface_bitset = NULL;
2764 * mono_unload_interface_ids:
2765 * @bitset: bit set of interface IDs
2767 * When an image is unloaded, the interface IDs associated with
2768 * the image are put back in the global pool of IDs so the numbers
2772 mono_unload_interface_ids (MonoBitSet *bitset)
2775 mono_bitset_sub (global_interface_bitset, bitset);
2780 mono_unload_interface_id (MonoClass *klass)
2782 if (global_interface_bitset && klass->interface_id) {
2784 mono_bitset_clear (global_interface_bitset, klass->interface_id);
2790 * mono_get_unique_iid:
2793 * Assign a unique integer ID to the interface represented by @class.
2794 * The ID will positive and as small as possible.
2795 * LOCKING: Acquires the classes lock.
2796 * Returns: The new ID.
2799 mono_get_unique_iid (MonoClass *klass)
2803 g_assert (MONO_CLASS_IS_INTERFACE (klass));
2807 if (!global_interface_bitset) {
2808 global_interface_bitset = mono_bitset_new (128, 0);
2811 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2813 int old_size = mono_bitset_size (global_interface_bitset);
2814 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2815 mono_bitset_free (global_interface_bitset);
2816 global_interface_bitset = new_set;
2819 mono_bitset_set (global_interface_bitset, iid);
2820 /* set the bit also in the per-image set */
2821 if (!klass->generic_class) {
2822 if (klass->image->interface_bitset) {
2823 if (iid >= mono_bitset_size (klass->image->interface_bitset)) {
2824 MonoBitSet *new_set = mono_bitset_clone (klass->image->interface_bitset, iid + 1);
2825 mono_bitset_free (klass->image->interface_bitset);
2826 klass->image->interface_bitset = new_set;
2829 klass->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2831 mono_bitset_set (klass->image->interface_bitset, iid);
2836 #ifndef MONO_SMALL_CONFIG
2837 if (mono_print_vtable) {
2839 char *type_name = mono_type_full_name (&klass->byval_arg);
2840 if (klass->generic_class && !klass->generic_class->context.class_inst->is_open) {
2841 generic_id = klass->generic_class->context.class_inst->id;
2842 g_assert (generic_id != 0);
2846 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, klass->image->name, type_name, generic_id);
2851 g_assert (iid <= 65535);
2856 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2861 mono_class_setup_interfaces (klass, error);
2862 return_if_nok (error);
2864 for (i = 0; i < klass->interface_count; i++) {
2865 ic = klass->interfaces [i];
2868 *res = g_ptr_array_new ();
2869 g_ptr_array_add (*res, ic);
2870 mono_class_init (ic);
2871 if (mono_class_has_failure (ic)) {
2872 mono_error_set_type_load_class (error, ic, "Error Loading class");
2876 collect_implemented_interfaces_aux (ic, res, error);
2877 return_if_nok (error);
2882 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2884 GPtrArray *res = NULL;
2886 collect_implemented_interfaces_aux (klass, &res, error);
2887 if (!mono_error_ok (error)) {
2889 g_ptr_array_free (res, TRUE);
2896 compare_interface_ids (const void *p_key, const void *p_element) {
2897 const MonoClass *key = (const MonoClass *)p_key;
2898 const MonoClass *element = *(const MonoClass **)p_element;
2900 return (key->interface_id - element->interface_id);
2903 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2905 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2906 MonoClass **result = (MonoClass **)mono_binary_search (
2908 klass->interfaces_packed,
2909 klass->interface_offsets_count,
2910 sizeof (MonoClass *),
2911 compare_interface_ids);
2913 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2920 * mono_class_interface_offset_with_variance:
2922 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2923 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2925 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2927 * FIXME figure out MS disambiguation rules and fix this function.
2930 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2931 int i = mono_class_interface_offset (klass, itf);
2932 *non_exact_match = FALSE;
2936 if (!mono_class_has_variant_generic_params (itf))
2939 for (i = 0; i < klass->interface_offsets_count; i++) {
2940 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2941 *non_exact_match = TRUE;
2942 return klass->interface_offsets_packed [i];
2950 print_implemented_interfaces (MonoClass *klass) {
2953 GPtrArray *ifaces = NULL;
2955 int ancestor_level = 0;
2957 name = mono_type_get_full_name (klass);
2958 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2961 for (i = 0; i < klass->interface_offsets_count; i++)
2962 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2963 klass->interfaces_packed [i]->interface_id,
2964 klass->interface_offsets_packed [i],
2965 klass->interfaces_packed [i]->method.count,
2966 klass->interfaces_packed [i]->name_space,
2967 klass->interfaces_packed [i]->name );
2968 printf ("Interface flags: ");
2969 for (i = 0; i <= klass->max_interface_id; i++)
2970 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2971 printf ("(%d,T)", i);
2973 printf ("(%d,F)", i);
2975 printf ("Dump interface flags:");
2976 #ifdef COMPRESSED_INTERFACE_BITMAP
2978 const uint8_t* p = klass->interface_bitmap;
2979 i = klass->max_interface_id;
2981 printf (" %d x 00 %02X", p [0], p [1]);
2987 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
2988 printf (" %02X", klass->interface_bitmap [i]);
2991 while (klass != NULL) {
2992 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
2993 ifaces = mono_class_get_implemented_interfaces (klass, &error);
2994 if (!mono_error_ok (&error)) {
2995 printf (" Type failed due to %s\n", mono_error_get_message (&error));
2996 mono_error_cleanup (&error);
2997 } else if (ifaces) {
2998 for (i = 0; i < ifaces->len; i++) {
2999 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3000 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
3001 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3003 mono_class_interface_offset (klass, ic),
3008 g_ptr_array_free (ifaces, TRUE);
3011 klass = klass->parent;
3016 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
3019 args [0] = &arg0->byval_arg;
3021 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
3025 array_class_get_if_rank (MonoClass *klass, guint rank)
3027 return rank ? mono_array_class_get (klass, rank) : klass;
3031 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
3033 valuetype_types [0] = eclass;
3034 if (eclass == mono_defaults.int16_class)
3035 valuetype_types [1] = mono_defaults.uint16_class;
3036 else if (eclass == mono_defaults.uint16_class)
3037 valuetype_types [1] = mono_defaults.int16_class;
3038 else if (eclass == mono_defaults.int32_class)
3039 valuetype_types [1] = mono_defaults.uint32_class;
3040 else if (eclass == mono_defaults.uint32_class)
3041 valuetype_types [1] = mono_defaults.int32_class;
3042 else if (eclass == mono_defaults.int64_class)
3043 valuetype_types [1] = mono_defaults.uint64_class;
3044 else if (eclass == mono_defaults.uint64_class)
3045 valuetype_types [1] = mono_defaults.int64_class;
3046 else if (eclass == mono_defaults.byte_class)
3047 valuetype_types [1] = mono_defaults.sbyte_class;
3048 else if (eclass == mono_defaults.sbyte_class)
3049 valuetype_types [1] = mono_defaults.byte_class;
3050 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
3051 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
3054 /* this won't be needed once bug #325495 is completely fixed
3055 * though we'll need something similar to know which interfaces to allow
3056 * in arrays when they'll be lazyly created
3058 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
3059 * MS returns diferrent types based on which instance is called. For example:
3060 * object obj = new byte[10][];
3061 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
3062 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
3065 * Fixing this should kill quite some code, save some bits and improve compatibility.
3068 get_implicit_generic_array_interfaces (MonoClass *klass, int *num, int *is_enumerator)
3070 MonoClass *eclass = klass->element_class;
3071 static MonoClass* generic_icollection_class = NULL;
3072 static MonoClass* generic_ienumerable_class = NULL;
3073 static MonoClass* generic_ienumerator_class = NULL;
3074 static MonoClass* generic_ireadonlylist_class = NULL;
3075 static MonoClass* generic_ireadonlycollection_class = NULL;
3076 MonoClass *valuetype_types[2] = { NULL, NULL };
3077 MonoClass **interfaces = NULL;
3078 int i, nifaces, interface_count, real_count, original_rank;
3080 gboolean internal_enumerator;
3081 gboolean eclass_is_valuetype;
3083 if (!mono_defaults.generic_ilist_class) {
3087 internal_enumerator = FALSE;
3088 eclass_is_valuetype = FALSE;
3089 original_rank = eclass->rank;
3090 if (klass->byval_arg.type != MONO_TYPE_SZARRAY) {
3091 if (klass->generic_class && klass->nested_in == mono_defaults.array_class && strcmp (klass->name, "InternalEnumerator`1") == 0) {
3093 * For a Enumerator<T[]> we need to get the list of interfaces for T.
3095 eclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
3096 original_rank = eclass->rank;
3098 eclass = eclass->element_class;
3099 internal_enumerator = TRUE;
3100 *is_enumerator = TRUE;
3108 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
3109 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
3111 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
3113 if (!generic_icollection_class) {
3114 generic_icollection_class = mono_class_load_from_name (mono_defaults.corlib,
3115 "System.Collections.Generic", "ICollection`1");
3116 generic_ienumerable_class = mono_class_load_from_name (mono_defaults.corlib,
3117 "System.Collections.Generic", "IEnumerable`1");
3118 generic_ienumerator_class = mono_class_load_from_name (mono_defaults.corlib,
3119 "System.Collections.Generic", "IEnumerator`1");
3120 generic_ireadonlylist_class = mono_class_load_from_name (mono_defaults.corlib,
3121 "System.Collections.Generic", "IReadOnlyList`1");
3122 generic_ireadonlycollection_class = mono_class_load_from_name (mono_defaults.corlib,
3123 "System.Collections.Generic", "IReadOnlyCollection`1");
3126 mono_class_init (eclass);
3129 * Arrays in 2.0 need to implement a number of generic interfaces
3130 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
3131 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
3132 * We collect the types needed to build the
3133 * instantiations in interfaces at intervals of 3/5, because 3/5 are
3134 * the generic interfaces needed to implement.
3136 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
3137 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
3139 if (eclass->valuetype) {
3140 nifaces = generic_ireadonlylist_class ? 5 : 3;
3141 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
3143 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
3144 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
3145 if (internal_enumerator) {
3147 if (valuetype_types [1])
3151 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3152 interfaces [0] = valuetype_types [0];
3153 if (valuetype_types [1])
3154 interfaces [nifaces] = valuetype_types [1];
3156 eclass_is_valuetype = TRUE;
3159 int idepth = eclass->idepth;
3160 if (!internal_enumerator)
3162 nifaces = generic_ireadonlylist_class ? 2 : 3;
3164 // FIXME: This doesn't seem to work/required for generic params
3165 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
3166 mono_class_setup_interface_offsets (eclass);
3168 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
3169 /* we add object for interfaces and the supertypes for the other
3170 * types. The last of the supertypes is the element class itself which we
3171 * already created the explicit interfaces for (so we include it for IEnumerator
3172 * and exclude it for arrays).
3174 if (MONO_CLASS_IS_INTERFACE (eclass))
3177 interface_count += idepth;
3178 if (eclass->rank && eclass->element_class->valuetype) {
3179 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3180 if (valuetype_types [1])
3183 /* IList, ICollection, IEnumerable, IReadOnlyList */
3184 interface_count *= nifaces;
3185 real_count = interface_count;
3186 if (internal_enumerator) {
3187 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3188 if (valuetype_types [1])
3191 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3192 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3193 interfaces [0] = mono_defaults.object_class;
3197 for (i = 0; i < idepth; i++) {
3198 mono_class_init (eclass->supertypes [i]);
3199 interfaces [j] = eclass->supertypes [i];
3203 if (all_interfaces) {
3204 for (i = 0; i < eclass->interface_offsets_count; i++) {
3205 interfaces [j] = eclass->interfaces_packed [i];
3209 for (i = 0; i < eclass->interface_count; i++) {
3210 interfaces [j] = eclass->interfaces [i];
3214 if (valuetype_types [1]) {
3215 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3220 /* instantiate the generic interfaces */
3221 for (i = 0; i < interface_count; i += nifaces) {
3222 MonoClass *iface = interfaces [i];
3224 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3225 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3227 if (eclass->valuetype) {
3228 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3229 if (generic_ireadonlylist_class) {
3230 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3231 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3234 if (!generic_ireadonlylist_class)
3235 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3238 if (internal_enumerator) {
3240 /* instantiate IEnumerator<iface> */
3241 for (i = 0; i < interface_count; i++) {
3242 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3244 j = interface_count;
3245 if (!eclass_is_valuetype) {
3246 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3247 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3250 for (i = 0; i < eclass->idepth; i++) {
3251 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3255 for (i = 0; i < eclass->interface_offsets_count; i++) {
3256 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3260 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3262 if (valuetype_types [1])
3263 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3267 char *type_name = mono_type_get_name_full (&klass->byval_arg, 0);
3268 for (i = 0; i < real_count; ++i) {
3269 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3270 g_print ("%s implements %s\n", type_name, name);
3281 find_array_interface (MonoClass *klass, const char *name)
3284 for (i = 0; i < klass->interface_count; ++i) {
3285 if (strcmp (klass->interfaces [i]->name, name) == 0)
3292 * Return the number of virtual methods.
3293 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3294 * Return -1 on failure.
3295 * FIXME It would be nice if this information could be cached somewhere.
3298 count_virtual_methods (MonoClass *klass)
3302 klass = mono_class_get_generic_type_definition (klass); /*We can find this information by looking at the GTD*/
3304 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
3305 mono_class_setup_methods (klass);
3306 if (mono_class_has_failure (klass))
3309 for (i = 0; i < klass->method.count; ++i) {
3310 flags = klass->methods [i]->flags;
3311 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3315 for (i = 0; i < klass->method.count; ++i) {
3316 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
3318 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3326 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3334 m = (l + num_ifaces) / 2;
3335 if (interfaces_full [m] == ic)
3337 if (l == num_ifaces)
3339 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3348 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3350 int i = find_interface (num_ifaces, interfaces_full, ic);
3352 return interface_offsets_full [i];
3357 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3359 int i = find_interface (num_ifaces, interfaces_full, ic);
3363 interface_offsets_full [i] = offset;
3366 for (i = 0; i < num_ifaces; ++i) {
3367 if (interfaces_full [i]) {
3369 if (interfaces_full [i]->interface_id < ic->interface_id)
3372 while (end < num_ifaces && interfaces_full [end]) end++;
3373 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3374 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3376 interfaces_full [i] = ic;
3377 interface_offsets_full [i] = offset;
3383 #ifdef COMPRESSED_INTERFACE_BITMAP
3386 * Compressed interface bitmap design.
3388 * Interface bitmaps take a large amount of memory, because their size is
3389 * linear with the maximum interface id assigned in the process (each interface
3390 * is assigned a unique id as it is loaded). The number of interface classes
3391 * is high because of the many implicit interfaces implemented by arrays (we'll
3392 * need to lazy-load them in the future).
3393 * Most classes implement a very small number of interfaces, so the bitmap is
3394 * sparse. This bitmap needs to be checked by interface casts, so access to the
3395 * needed bit must be fast and doable with few jit instructions.
3397 * The current compression format is as follows:
3398 * *) it is a sequence of one or more two-byte elements
3399 * *) the first byte in the element is the count of empty bitmap bytes
3400 * at the current bitmap position
3401 * *) the second byte in the element is an actual bitmap byte at the current
3404 * As an example, the following compressed bitmap bytes:
3405 * 0x07 0x01 0x00 0x7
3406 * correspond to the following bitmap:
3407 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3409 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3410 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3411 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3415 * mono_compress_bitmap:
3416 * @dest: destination buffer
3417 * @bitmap: bitmap buffer
3418 * @size: size of @bitmap in bytes
3420 * This is a mono internal function.
3421 * The @bitmap data is compressed into a format that is small but
3422 * still searchable in few instructions by the JIT and runtime.
3423 * The compressed data is stored in the buffer pointed to by the
3424 * @dest array. Passing a #NULL value for @dest allows to just compute
3425 * the size of the buffer.
3426 * This compression algorithm assumes the bits set in the bitmap are
3427 * few and far between, like in interface bitmaps.
3428 * Returns: The size of the compressed bitmap in bytes.
3431 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3435 const uint8_t *end = bitmap + size;
3436 while (bitmap < end) {
3437 if (*bitmap || numz == 255) {
3461 * mono_class_interface_match:
3462 * @bitmap: a compressed bitmap buffer
3463 * @id: the index to check in the bitmap
3465 * This is a mono internal function.
3466 * Checks if a bit is set in a compressed interface bitmap. @id must
3467 * be already checked for being smaller than the maximum id encoded in the
3470 * Returns: A non-zero value if bit @id is set in the bitmap @bitmap,
3474 mono_class_interface_match (const uint8_t *bitmap, int id)
3477 id -= bitmap [0] * 8;
3481 return bitmap [1] & (1 << id);
3490 * LOCKING: this is supposed to be called with the loader lock held.
3491 * Return -1 on failure and set klass->has_failure and store a MonoErrorBoxed with the details.
3494 setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite)
3498 int i, j, max_iid, num_ifaces;
3499 MonoClass **interfaces_full = NULL;
3500 int *interface_offsets_full = NULL;
3502 GPtrArray **ifaces_array = NULL;
3503 int interface_offsets_count;
3504 MonoClass **array_interfaces = NULL;
3505 int num_array_interfaces;
3506 int is_enumerator = FALSE;
3508 mono_class_setup_supertypes (klass);
3510 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3511 * implicit interfaces have the property that they are assigned the same slot in the
3512 * vtables for compatible interfaces
3514 array_interfaces = get_implicit_generic_array_interfaces (klass, &num_array_interfaces, &is_enumerator);
3516 /* compute maximum number of slots and maximum interface id */
3518 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3519 ifaces_array = g_new0 (GPtrArray *, klass->idepth);
3520 for (j = 0; j < klass->idepth; j++) {
3521 k = klass->supertypes [j];
3522 num_ifaces += k->interface_count;
3523 for (i = 0; i < k->interface_count; i++) {
3524 ic = k->interfaces [i];
3527 mono_class_init (ic);
3529 if (max_iid < ic->interface_id)
3530 max_iid = ic->interface_id;
3532 ifaces = mono_class_get_implemented_interfaces (k, &error);
3533 if (!mono_error_ok (&error)) {
3534 char *name = mono_type_get_full_name (k);
3535 mono_class_set_type_load_failure (klass, "Error getting the interfaces of %s due to %s", name, mono_error_get_message (&error));
3537 mono_error_cleanup (&error);
3542 num_ifaces += ifaces->len;
3543 for (i = 0; i < ifaces->len; ++i) {
3544 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3545 if (max_iid < ic->interface_id)
3546 max_iid = ic->interface_id;
3548 ifaces_array [j] = ifaces;
3552 for (i = 0; i < num_array_interfaces; ++i) {
3553 ic = array_interfaces [i];
3554 mono_class_init (ic);
3555 if (max_iid < ic->interface_id)
3556 max_iid = ic->interface_id;
3559 if (MONO_CLASS_IS_INTERFACE (klass)) {
3561 if (max_iid < klass->interface_id)
3562 max_iid = klass->interface_id;
3564 klass->max_interface_id = max_iid;
3565 /* compute vtable offset for interfaces */
3566 interfaces_full = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3567 interface_offsets_full = (int *)g_malloc (sizeof (int) * num_ifaces);
3569 for (i = 0; i < num_ifaces; i++) {
3570 interface_offsets_full [i] = -1;
3573 /* skip the current class */
3574 for (j = 0; j < klass->idepth - 1; j++) {
3575 k = klass->supertypes [j];
3576 ifaces = ifaces_array [j];
3579 for (i = 0; i < ifaces->len; ++i) {
3581 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3583 /*Force the sharing of interface offsets between parent and subtypes.*/
3584 io = mono_class_interface_offset (k, ic);
3586 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3591 g_assert (klass == klass->supertypes [klass->idepth - 1]);
3592 ifaces = ifaces_array [klass->idepth - 1];
3594 for (i = 0; i < ifaces->len; ++i) {
3596 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3597 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3599 count = count_virtual_methods (ic);
3601 char *name = mono_type_get_full_name (ic);
3602 mono_class_set_type_load_failure (klass, "Error calculating interface offset of %s", name);
3611 if (MONO_CLASS_IS_INTERFACE (klass))
3612 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, klass, cur_slot, TRUE);
3614 if (num_array_interfaces) {
3615 if (is_enumerator) {
3616 int ienumerator_idx = find_array_interface (klass, "IEnumerator`1");
3617 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ienumerator_idx]);
3618 g_assert (ienumerator_offset >= 0);
3619 for (i = 0; i < num_array_interfaces; ++i) {
3620 ic = array_interfaces [i];
3621 if (strcmp (ic->name, "IEnumerator`1") == 0)
3622 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3624 g_assert_not_reached ();
3625 /*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);*/
3628 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3629 int ilist_iface_idx = find_array_interface (klass, "IList`1");
3630 MonoClass* ilist_class = klass->interfaces [ilist_iface_idx];
3631 int ireadonlylist_iface_idx = find_array_interface (klass, "IReadOnlyList`1");
3632 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? klass->interfaces [ireadonlylist_iface_idx] : NULL;
3633 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3634 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3635 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3636 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ilist_iface_idx]);
3637 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3638 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3639 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ireadonlylist_iface_idx]) : -1;
3640 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3641 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3642 for (i = 0; i < num_array_interfaces; ++i) {
3644 ic = array_interfaces [i];
3645 if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
3646 offset = ilist_offset;
3647 else if (strcmp (ic->name, "ICollection`1") == 0)
3648 offset = icollection_offset;
3649 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3650 offset = ienumerable_offset;
3651 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3652 offset = ireadonlylist_offset;
3653 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3654 offset = ireadonlycollection_offset;
3656 g_assert_not_reached ();
3657 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3658 /*g_print ("type %s has %s offset at %d (%s)\n", klass->name, ic->name, offset, klass->interfaces [0]->name);*/
3663 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3664 if (interface_offsets_full [i] != -1) {
3665 interface_offsets_count ++;
3670 * We might get called multiple times:
3671 * - mono_class_init ()
3672 * - mono_class_setup_vtable ().
3673 * - mono_class_setup_interface_offsets ().
3674 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3675 * means we have to overwrite those when called from other places (#4440).
3677 if (klass->interfaces_packed) {
3679 g_assert (klass->interface_offsets_count == interface_offsets_count);
3683 klass->interface_offsets_count = interface_offsets_count;
3684 klass->interfaces_packed = (MonoClass **)mono_class_alloc (klass, sizeof (MonoClass*) * interface_offsets_count);
3685 klass->interface_offsets_packed = (guint16 *)mono_class_alloc (klass, sizeof (guint16) * interface_offsets_count);
3686 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3687 #ifdef COMPRESSED_INTERFACE_BITMAP
3688 bitmap = g_malloc0 (bsize);
3690 bitmap = (uint8_t *)mono_class_alloc0 (klass, bsize);
3692 for (i = 0; i < interface_offsets_count; i++) {
3693 int id = interfaces_full [i]->interface_id;
3694 bitmap [id >> 3] |= (1 << (id & 7));
3695 klass->interfaces_packed [i] = interfaces_full [i];
3696 klass->interface_offsets_packed [i] = interface_offsets_full [i];
3697 /*if (num_array_interfaces)
3698 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]);*/
3700 #ifdef COMPRESSED_INTERFACE_BITMAP
3701 i = mono_compress_bitmap (NULL, bitmap, bsize);
3702 klass->interface_bitmap = mono_class_alloc0 (klass, i);
3703 mono_compress_bitmap (klass->interface_bitmap, bitmap, bsize);
3706 klass->interface_bitmap = bitmap;
3711 g_free (interfaces_full);
3712 g_free (interface_offsets_full);
3713 g_free (array_interfaces);
3714 for (i = 0; i < klass->idepth; i++) {
3715 ifaces = ifaces_array [i];
3717 g_ptr_array_free (ifaces, TRUE);
3719 g_free (ifaces_array);
3721 //printf ("JUST DONE: ");
3722 //print_implemented_interfaces (klass);
3728 * Setup interface offsets for interfaces.
3730 * - klass->max_interface_id
3731 * - klass->interface_offsets_count
3732 * - klass->interfaces_packed
3733 * - klass->interface_offsets_packed
3734 * - klass->interface_bitmap
3736 * This function can fail @class.
3739 mono_class_setup_interface_offsets (MonoClass *klass)
3741 mono_loader_lock ();
3743 setup_interface_offsets (klass, 0, FALSE);
3745 mono_loader_unlock ();
3748 /*Checks if @klass has @parent as one of it's parents type gtd
3752 * Bar<T> : Foo<Bar<Bar<T>>>
3756 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3758 klass = mono_class_get_generic_type_definition (klass);
3759 parent = mono_class_get_generic_type_definition (parent);
3760 mono_class_setup_supertypes (klass);
3761 mono_class_setup_supertypes (parent);
3763 return klass->idepth >= parent->idepth &&
3764 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3768 mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup)
3770 MonoGenericInst *ginst;
3772 if (!klass->generic_class) {
3773 mono_class_setup_vtable_full (klass, in_setup);
3774 return !mono_class_has_failure (klass);
3777 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup);
3778 if (mono_class_has_failure (klass->generic_class->container_class)) {
3779 mono_class_set_type_load_failure (klass, "Failed to load generic definition vtable");
3783 ginst = klass->generic_class->context.class_inst;
3784 for (i = 0; i < ginst->type_argc; ++i) {
3786 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3788 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3789 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3790 if (mono_class_has_gtd_parent (klass, arg) || mono_class_has_gtd_parent (arg, klass))
3792 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3793 mono_class_set_type_load_failure (klass, "Failed to load generic parameter %d", i);
3801 * mono_class_setup_vtable:
3803 * Creates the generic vtable of CLASS.
3804 * Initializes the following fields in MonoClass:
3807 * Plus all the fields initialized by setup_interface_offsets ().
3808 * If there is an error during vtable construction, klass->has_failure
3809 * is set and details are stored in a MonoErrorBoxed.
3811 * LOCKING: Acquires the loader lock.
3814 mono_class_setup_vtable (MonoClass *klass)
3816 mono_class_setup_vtable_full (klass, NULL);
3820 mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
3823 MonoMethod **overrides;
3824 MonoGenericContext *context;
3832 if (MONO_CLASS_IS_INTERFACE (klass)) {
3833 /* This sets method->slot for all methods if this is an interface */
3834 mono_class_setup_methods (klass);
3838 if (mono_class_has_failure (klass))
3841 if (g_list_find (in_setup, klass))
3844 mono_loader_lock ();
3846 if (klass->vtable) {
3847 mono_loader_unlock ();
3851 mono_stats.generic_vtable_count ++;
3852 in_setup = g_list_prepend (in_setup, klass);
3854 if (klass->generic_class) {
3855 if (!mono_class_check_vtable_constraints (klass, in_setup)) {
3856 mono_loader_unlock ();
3857 g_list_remove (in_setup, klass);
3861 context = mono_class_get_context (klass);
3862 type_token = klass->generic_class->container_class->type_token;
3864 context = (MonoGenericContext *) klass->generic_container;
3865 type_token = klass->type_token;
3868 if (image_is_dynamic (klass->image)) {
3869 /* Generic instances can have zero method overrides without causing any harm.
3870 * This is true since we don't do layout all over again for them, we simply inflate
3871 * the layout of the parent.
3873 mono_reflection_get_dynamic_overrides (klass, &overrides, &onum, &error);
3874 if (!is_ok (&error)) {
3875 mono_loader_unlock ();
3876 g_list_remove (in_setup, klass);
3877 mono_class_set_type_load_failure (klass, "Could not load list of method overrides due to %s", mono_error_get_message (&error));
3878 mono_error_cleanup (&error);
3882 /* The following call fails if there are missing methods in the type */
3883 /* FIXME it's probably a good idea to avoid this for generic instances. */
3884 ok = mono_class_get_overrides_full (klass->image, type_token, &overrides, &onum, context);
3888 mono_class_setup_vtable_general (klass, overrides, onum, in_setup);
3890 mono_class_set_type_load_failure (klass, "Could not load list of method overrides");
3894 mono_loader_unlock ();
3895 g_list_remove (in_setup, klass);
3900 #define DEBUG_INTERFACE_VTABLE_CODE 0
3901 #define TRACE_INTERFACE_VTABLE_CODE 0
3902 #define VERIFY_INTERFACE_VTABLE_CODE 0
3903 #define VTABLE_SELECTOR (1)
3905 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3906 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3907 if (!(VTABLE_SELECTOR)) break; \
3911 #define DEBUG_INTERFACE_VTABLE(stmt)
3914 #if TRACE_INTERFACE_VTABLE_CODE
3915 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3916 if (!(VTABLE_SELECTOR)) break; \
3920 #define TRACE_INTERFACE_VTABLE(stmt)
3923 #if VERIFY_INTERFACE_VTABLE_CODE
3924 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3925 if (!(VTABLE_SELECTOR)) break; \
3929 #define VERIFY_INTERFACE_VTABLE(stmt)
3933 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3935 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3939 GString *res = g_string_new ("");
3941 g_string_append_c (res, '(');
3942 for (i = 0; i < sig->param_count; ++i) {
3944 g_string_append_c (res, ',');
3945 mono_type_get_desc (res, sig->params [i], include_namespace);
3947 g_string_append (res, ")=>");
3948 if (sig->ret != NULL) {
3949 mono_type_get_desc (res, sig->ret, include_namespace);
3951 g_string_append (res, "NULL");
3954 g_string_free (res, FALSE);
3958 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3959 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3960 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3961 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3969 is_wcf_hack_disabled (void)
3971 static gboolean disabled;
3972 static gboolean inited = FALSE;
3974 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3981 check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
3983 MonoMethodSignature *cmsig, *imsig;
3984 if (strcmp (im->name, cm->name) == 0) {
3985 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3986 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3989 if (! slot_is_empty) {
3990 if (require_newslot) {
3991 if (! interface_is_explicitly_implemented_by_class) {
3992 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3995 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3996 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
4000 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
4003 cmsig = mono_method_signature (cm);
4004 imsig = mono_method_signature (im);
4005 if (!cmsig || !imsig) {
4006 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
4010 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4011 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
4012 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4013 TRACE_INTERFACE_VTABLE (printf ("]"));
4016 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
4017 if (mono_security_core_clr_enabled ())
4018 mono_security_core_clr_check_override (klass, cm, im);
4020 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
4021 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4022 char *body_name = mono_method_full_name (cm, TRUE);
4023 char *decl_name = mono_method_full_name (im, TRUE);
4024 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4032 MonoClass *ic = im->klass;
4033 const char *ic_name_space = ic->name_space;
4034 const char *ic_name = ic->name;
4037 if (! require_newslot) {
4038 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
4041 if (cm->klass->rank == 0) {
4042 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
4045 cmsig = mono_method_signature (cm);
4046 imsig = mono_method_signature (im);
4047 if (!cmsig || !imsig) {
4048 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
4052 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4053 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
4054 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4055 TRACE_INTERFACE_VTABLE (printf ("]"));
4058 if (mono_class_get_image (ic) != mono_defaults.corlib) {
4059 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
4062 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
4063 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
4066 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))) {
4067 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
4071 subname = strstr (cm->name, ic_name_space);
4072 if (subname != cm->name) {
4073 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
4076 subname += strlen (ic_name_space);
4077 if (subname [0] != '.') {
4078 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
4082 if (strstr (subname, ic_name) != subname) {
4083 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
4086 subname += strlen (ic_name);
4087 if (subname [0] != '.') {
4088 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
4092 if (strcmp (subname, im->name) != 0) {
4093 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
4097 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
4098 if (mono_security_core_clr_enabled ())
4099 mono_security_core_clr_check_override (klass, cm, im);
4101 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
4102 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4103 char *body_name = mono_method_full_name (cm, TRUE);
4104 char *decl_name = mono_method_full_name (im, TRUE);
4105 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4115 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
4117 foreach_override (gpointer key, gpointer value, gpointer user_data) {
4118 MonoMethod *method = key;
4119 MonoMethod *override = value;
4120 MonoClass *method_class = mono_method_get_class (method);
4121 MonoClass *override_class = mono_method_get_class (override);
4123 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
4124 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
4125 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
4128 print_overrides (GHashTable *override_map, const char *message) {
4130 printf ("Override map \"%s\" START:\n", message);
4131 g_hash_table_foreach (override_map, foreach_override, NULL);
4132 printf ("Override map \"%s\" END.\n", message);
4134 printf ("Override map \"%s\" EMPTY.\n", message);
4138 print_vtable_full (MonoClass *klass, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
4139 char *full_name = mono_type_full_name (&klass->byval_arg);
4143 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
4145 if (print_interfaces) {
4146 print_implemented_interfaces (klass);
4147 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
4150 if (klass->parent) {
4151 parent_size = klass->parent->vtable_size;
4155 for (i = 0; i < size; ++i) {
4156 MonoMethod *cm = vtable [i];
4157 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
4158 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
4160 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
4168 #if VERIFY_INTERFACE_VTABLE_CODE
4170 mono_method_try_get_vtable_index (MonoMethod *method)
4172 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4173 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4174 if (imethod->declaring->is_generic)
4175 return imethod->declaring->slot;
4177 return method->slot;
4181 mono_class_verify_vtable (MonoClass *klass)
4184 char *full_name = mono_type_full_name (&klass->byval_arg);
4186 printf ("*** Verifying VTable of class '%s' \n", full_name);
4190 if (!klass->methods)
4193 for (i = 0; i < klass->method.count; ++i) {
4194 MonoMethod *cm = klass->methods [i];
4197 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4201 full_name = mono_method_full_name (cm, TRUE);
4203 slot = mono_method_try_get_vtable_index (cm);
4205 if (slot >= klass->vtable_size) {
4206 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, klass->vtable_size);
4210 if (slot >= 0 && klass->vtable [slot] != cm && (klass->vtable [slot])) {
4211 char *other_name = klass->vtable [slot] ? mono_method_full_name (klass->vtable [slot], TRUE) : g_strdup ("[null value]");
4212 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4213 g_free (other_name);
4216 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4223 print_unimplemented_interface_method_info (MonoClass *klass, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4225 char *method_signature;
4228 for (index = 0; index < onum; ++index) {
4229 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4230 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4232 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4233 type_name = mono_type_full_name (&klass->byval_arg);
4234 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4235 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4236 g_free (method_signature);
4238 mono_class_setup_methods (klass);
4239 if (mono_class_has_failure (klass)) {
4240 char *name = mono_type_get_full_name (klass);
4241 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4245 for (index = 0; index < klass->method.count; ++index) {
4246 MonoMethod *cm = klass->methods [index];
4247 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4249 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4250 g_free (method_signature);
4255 mono_method_get_method_definition (MonoMethod *method)
4257 while (method->is_inflated)
4258 method = ((MonoMethodInflated*)method)->declaring;
4263 verify_class_overrides (MonoClass *klass, MonoMethod **overrides, int onum)
4267 for (i = 0; i < onum; ++i) {
4268 MonoMethod *decl = overrides [i * 2];
4269 MonoMethod *body = overrides [i * 2 + 1];
4271 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (klass)) {
4272 mono_class_set_type_load_failure (klass, "Method belongs to a different class than the declared one");
4276 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4277 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4278 mono_class_set_type_load_failure (klass, "Method must not be static to override a base type");
4280 mono_class_set_type_load_failure (klass, "Method must be virtual to override a base type");
4284 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4285 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4286 mono_class_set_type_load_failure (klass, "Cannot override a static method in a base type");
4288 mono_class_set_type_load_failure (klass, "Cannot override a non virtual method in a base type");
4292 if (!mono_class_is_assignable_from_slow (decl->klass, klass)) {
4293 mono_class_set_type_load_failure (klass, "Method overrides a class or interface that is not extended or implemented by this type");
4297 body = mono_method_get_method_definition (body);
4298 decl = mono_method_get_method_definition (decl);
4300 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4301 char *body_name = mono_method_full_name (body, TRUE);
4302 char *decl_name = mono_method_full_name (decl, TRUE);
4303 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4313 mono_class_need_stelemref_method (MonoClass *klass)
4315 return klass->rank == 1 && MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg);
4319 * LOCKING: this is supposed to be called with the loader lock held.
4322 mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int onum, GList *in_setup)
4326 MonoMethod **vtable;
4327 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4328 GPtrArray *ifaces = NULL;
4329 GHashTable *override_map = NULL;
4331 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4332 int first_non_interface_slot;
4334 GSList *virt_methods = NULL, *l;
4335 int stelemref_slot = 0;
4340 if (overrides && !verify_class_overrides (klass, overrides, onum))
4343 ifaces = mono_class_get_implemented_interfaces (klass, &error);
4344 if (!mono_error_ok (&error)) {
4345 char *name = mono_type_get_full_name (klass);
4346 mono_class_set_type_load_failure (klass, "Could not resolve %s interfaces due to %s", name, mono_error_get_message (&error));
4348 mono_error_cleanup (&error);
4350 } else if (ifaces) {
4351 for (i = 0; i < ifaces->len; i++) {
4352 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
4353 max_vtsize += ic->method.count;
4355 g_ptr_array_free (ifaces, TRUE);
4359 if (klass->parent) {
4360 mono_class_init (klass->parent);
4361 mono_class_setup_vtable_full (klass->parent, in_setup);
4363 if (mono_class_has_failure (klass->parent)) {
4364 char *name = mono_type_get_full_name (klass->parent);
4365 mono_class_set_type_load_failure (klass, "Parent %s failed to load", name);
4370 max_vtsize += klass->parent->vtable_size;
4371 cur_slot = klass->parent->vtable_size;
4374 max_vtsize += klass->method.count;
4376 /*Array have a slot for stelemref*/
4377 if (mono_class_need_stelemref_method (klass)) {
4378 stelemref_slot = cur_slot;
4383 vtable = (MonoMethod **)alloca (sizeof (gpointer) * max_vtsize);
4384 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4386 /* printf ("METAINIT %s.%s\n", klass->name_space, klass->name); */
4388 cur_slot = setup_interface_offsets (klass, cur_slot, TRUE);
4389 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4392 max_iid = klass->max_interface_id;
4393 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4395 /* Optimized version for generic instances */
4396 if (klass->generic_class) {
4398 MonoClass *gklass = klass->generic_class->container_class;
4401 mono_class_setup_vtable_full (gklass, in_setup);
4402 if (mono_class_has_failure (gklass)) {
4403 mono_class_set_type_load_failure (klass, "");
4407 tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * gklass->vtable_size);
4408 klass->vtable_size = gklass->vtable_size;
4409 for (i = 0; i < gklass->vtable_size; ++i)
4410 if (gklass->vtable [i]) {
4411 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], klass, mono_class_get_context (klass), &error);
4412 if (!mono_error_ok (&error)) {
4413 mono_class_set_type_load_failure (klass, "Could not inflate method due to %s", mono_error_get_message (&error));
4414 mono_error_cleanup (&error);
4418 tmp [i]->slot = gklass->vtable [i]->slot;
4420 mono_memory_barrier ();
4421 klass->vtable = tmp;
4423 /* Have to set method->slot for abstract virtual methods */
4424 if (klass->methods && gklass->methods) {
4425 for (i = 0; i < klass->method.count; ++i)
4426 if (klass->methods [i]->slot == -1)
4427 klass->methods [i]->slot = gklass->methods [i]->slot;
4433 if (klass->parent && klass->parent->vtable_size) {
4434 MonoClass *parent = klass->parent;
4437 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4439 // Also inherit parent interface vtables, just as a starting point.
4440 // This is needed otherwise bug-77127.exe fails when the property methods
4441 // have different names in the iterface and the class, because for child
4442 // classes the ".override" information is not used anymore.
4443 for (i = 0; i < parent->interface_offsets_count; i++) {
4444 MonoClass *parent_interface = parent->interfaces_packed [i];
4445 int interface_offset = mono_class_interface_offset (klass, parent_interface);
4446 /*FIXME this is now dead code as this condition will never hold true.
4447 Since interface offsets are inherited then the offset of an interface implemented
4448 by a parent will never be the out of it's vtable boundary.
4450 if (interface_offset >= parent->vtable_size) {
4451 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4454 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4455 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4456 for (j = 0; j < parent_interface->method.count && !mono_class_has_failure (klass); j++) {
4457 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4458 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4459 parent_interface_offset + j, parent_interface_offset, j,
4460 interface_offset + j, interface_offset, j));
4467 /*Array have a slot for stelemref*/
4468 if (mono_class_need_stelemref_method (klass)) {
4469 MonoMethod *method = mono_marshal_get_virtual_stelemref (klass);
4471 method->slot = stelemref_slot;
4473 g_assert (method->slot == stelemref_slot);
4475 vtable [stelemref_slot] = method;
4478 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4479 /* override interface methods */
4480 for (i = 0; i < onum; i++) {
4481 MonoMethod *decl = overrides [i*2];
4482 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4484 dslot = mono_method_get_vtable_slot (decl);
4486 mono_class_set_type_load_failure (klass, "");
4490 dslot += mono_class_interface_offset (klass, decl->klass);
4491 vtable [dslot] = overrides [i*2 + 1];
4492 vtable [dslot]->slot = dslot;
4494 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4496 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4498 if (mono_security_core_clr_enabled ())
4499 mono_security_core_clr_check_override (klass, vtable [dslot], decl);
4502 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4503 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4506 * Create a list of virtual methods to avoid calling
4507 * mono_class_get_virtual_methods () which is slow because of the metadata
4511 gpointer iter = NULL;
4514 virt_methods = NULL;
4515 while ((cm = mono_class_get_virtual_methods (klass, &iter))) {
4516 virt_methods = g_slist_prepend (virt_methods, cm);
4518 if (mono_class_has_failure (klass))
4522 // Loop on all implemented interfaces...
4523 for (i = 0; i < klass->interface_offsets_count; i++) {
4524 MonoClass *parent = klass->parent;
4526 gboolean interface_is_explicitly_implemented_by_class;
4529 ic = klass->interfaces_packed [i];
4530 ic_offset = mono_class_interface_offset (klass, ic);
4532 mono_class_setup_methods (ic);
4533 if (mono_class_has_failure (ic))
4536 // Check if this interface is explicitly implemented (instead of just inherited)
4537 if (parent != NULL) {
4538 int implemented_interfaces_index;
4539 interface_is_explicitly_implemented_by_class = FALSE;
4540 for (implemented_interfaces_index = 0; implemented_interfaces_index < klass->interface_count; implemented_interfaces_index++) {
4541 if (ic == klass->interfaces [implemented_interfaces_index]) {
4542 interface_is_explicitly_implemented_by_class = TRUE;
4547 interface_is_explicitly_implemented_by_class = TRUE;
4550 // Loop on all interface methods...
4551 for (im_index = 0; im_index < ic->method.count; im_index++) {
4552 MonoMethod *im = ic->methods [im_index];
4553 int im_slot = ic_offset + im->slot;
4554 MonoMethod *override_im = (override_map != NULL) ? (MonoMethod *)g_hash_table_lookup (override_map, im) : NULL;
4556 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4559 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4561 // If there is an explicit implementation, just use it right away,
4562 // otherwise look for a matching method
4563 if (override_im == NULL) {
4567 // First look for a suitable method among the class methods
4568 for (l = virt_methods; l; l = l->next) {
4569 cm = (MonoMethod *)l->data;
4570 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)));
4571 if (check_interface_method_override (klass, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
4572 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4573 vtable [im_slot] = cm;
4574 /* Why do we need this? */
4579 TRACE_INTERFACE_VTABLE (printf ("\n"));
4580 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4584 // If the slot is still empty, look in all the inherited virtual methods...
4585 if ((vtable [im_slot] == NULL) && klass->parent != NULL) {
4586 MonoClass *parent = klass->parent;
4587 // Reverse order, so that last added methods are preferred
4588 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4589 MonoMethod *cm = parent->vtable [cm_index];
4591 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));
4592 if ((cm != NULL) && check_interface_method_override (klass, im, cm, FALSE, FALSE, TRUE)) {
4593 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4594 vtable [im_slot] = cm;
4595 /* Why do we need this? */
4601 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4603 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4607 g_assert (vtable [im_slot] == override_im);
4612 // If the class is not abstract, check that all its interface slots are full.
4613 // The check is done here and not directly at the end of the loop above because
4614 // it can happen (for injected generic array interfaces) that the same slot is
4615 // processed multiple times (those interfaces have overlapping slots), and it
4616 // will not always be the first pass the one that fills the slot.
4617 if (! (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4618 for (i = 0; i < klass->interface_offsets_count; i++) {
4622 ic = klass->interfaces_packed [i];
4623 ic_offset = mono_class_interface_offset (klass, ic);
4625 for (im_index = 0; im_index < ic->method.count; im_index++) {
4626 MonoMethod *im = ic->methods [im_index];
4627 int im_slot = ic_offset + im->slot;
4629 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4632 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4633 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4634 if (vtable [im_slot] == NULL) {
4635 print_unimplemented_interface_method_info (klass, ic, im, im_slot, overrides, onum);
4642 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4643 for (l = virt_methods; l; l = l->next) {
4644 cm = (MonoMethod *)l->data;
4646 * If the method is REUSE_SLOT, we must check in the
4647 * base class for a method to override.
4649 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4651 for (k = klass->parent; k ; k = k->parent) {
4656 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4657 MonoMethodSignature *cmsig, *m1sig;
4659 cmsig = mono_method_signature (cm);
4660 m1sig = mono_method_signature (m1);
4662 if (!cmsig || !m1sig) {
4663 mono_class_set_type_load_failure (klass, "");
4667 if (!strcmp(cm->name, m1->name) &&
4668 mono_metadata_signature_equal (cmsig, m1sig)) {
4670 if (mono_security_core_clr_enabled ())
4671 mono_security_core_clr_check_override (klass, cm, m1);
4673 slot = mono_method_get_vtable_slot (m1);
4677 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4678 char *body_name = mono_method_full_name (cm, TRUE);
4679 char *decl_name = mono_method_full_name (m1, TRUE);
4680 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4686 g_assert (cm->slot < max_vtsize);
4688 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4689 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4690 mono_method_full_name (m1, 1), m1,
4691 mono_method_full_name (cm, 1), cm));
4692 g_hash_table_insert (override_map, m1, cm);
4696 if (mono_class_has_failure (k))
4706 /*Non final newslot methods must be given a non-interface vtable slot*/
4707 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4711 cm->slot = cur_slot++;
4713 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4714 vtable [cm->slot] = cm;
4717 /* override non interface methods */
4718 for (i = 0; i < onum; i++) {
4719 MonoMethod *decl = overrides [i*2];
4720 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4721 g_assert (decl->slot != -1);
4722 vtable [decl->slot] = overrides [i*2 + 1];
4723 overrides [i * 2 + 1]->slot = decl->slot;
4725 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4726 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4727 mono_method_full_name (decl, 1), decl,
4728 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4729 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4731 if (mono_security_core_clr_enabled ())
4732 mono_security_core_clr_check_override (klass, vtable [decl->slot], decl);
4737 * If a method occupies more than one place in the vtable, and it is
4738 * overriden, then change the other occurances too.
4743 for (i = 0; i < max_vtsize; ++i)
4745 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4747 cm = (MonoMethod *)g_hash_table_lookup (override_map, vtable [i]);
4752 g_hash_table_destroy (override_map);
4753 override_map = NULL;
4756 g_slist_free (virt_methods);
4757 virt_methods = NULL;
4759 /* Ensure that all vtable slots are filled with concrete instance methods */
4760 if (!(klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4761 for (i = 0; i < cur_slot; ++i) {
4762 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4763 char *type_name = mono_type_get_full_name (klass);
4764 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4765 mono_class_set_type_load_failure (klass, "Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name);
4767 g_free (method_name);
4773 if (klass->generic_class) {
4774 MonoClass *gklass = klass->generic_class->container_class;
4776 mono_class_init (gklass);
4778 klass->vtable_size = MAX (gklass->vtable_size, cur_slot);
4780 /* Check that the vtable_size value computed in mono_class_init () is correct */
4781 if (klass->vtable_size)
4782 g_assert (cur_slot == klass->vtable_size);
4783 klass->vtable_size = cur_slot;
4786 /* Try to share the vtable with our parent. */
4787 if (klass->parent && (klass->parent->vtable_size == klass->vtable_size) && (memcmp (klass->parent->vtable, vtable, sizeof (gpointer) * klass->vtable_size) == 0)) {
4788 mono_memory_barrier ();
4789 klass->vtable = klass->parent->vtable;
4791 MonoMethod **tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * klass->vtable_size);
4792 memcpy (tmp, vtable, sizeof (gpointer) * klass->vtable_size);
4793 mono_memory_barrier ();
4794 klass->vtable = tmp;
4797 DEBUG_INTERFACE_VTABLE (print_vtable_full (klass, klass->vtable, klass->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4798 if (mono_print_vtable) {
4801 print_implemented_interfaces (klass);
4803 for (i = 0; i <= max_iid; i++)
4804 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
4807 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&klass->byval_arg),
4808 klass->vtable_size, icount);
4810 for (i = 0; i < cur_slot; ++i) {
4815 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4816 mono_method_full_name (cm, TRUE));
4822 printf ("Interfaces %s.%s (max_iid = %d)\n", klass->name_space,
4823 klass->name, max_iid);
4825 for (i = 0; i < klass->interface_count; i++) {
4826 ic = klass->interfaces [i];
4827 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4828 mono_class_interface_offset (klass, ic),
4829 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4832 for (k = klass->parent; k ; k = k->parent) {
4833 for (i = 0; i < k->interface_count; i++) {
4834 ic = k->interfaces [i];
4835 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4836 mono_class_interface_offset (klass, ic),
4837 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4843 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (klass));
4848 char *name = mono_type_get_full_name (klass);
4849 mono_class_set_type_load_failure (klass, "VTable setup of type %s failed", name);
4852 g_hash_table_destroy (override_map);
4854 g_slist_free (virt_methods);
4859 * mono_method_get_vtable_slot:
4861 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4862 * LOCKING: Acquires the loader lock.
4864 * FIXME Use proper MonoError machinery here.
4867 mono_method_get_vtable_slot (MonoMethod *method)
4869 if (method->slot == -1) {
4870 mono_class_setup_vtable (method->klass);
4871 if (mono_class_has_failure (method->klass))
4873 if (method->slot == -1) {
4877 if (!method->klass->generic_class) {
4878 g_assert (method->is_inflated);
4879 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4882 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4883 g_assert (method->klass->generic_class);
4884 gklass = method->klass->generic_class->container_class;
4885 mono_class_setup_methods (method->klass);
4886 g_assert (method->klass->methods);
4887 for (i = 0; i < method->klass->method.count; ++i) {
4888 if (method->klass->methods [i] == method)
4891 g_assert (i < method->klass->method.count);
4892 g_assert (gklass->methods);
4893 method->slot = gklass->methods [i]->slot;
4895 g_assert (method->slot != -1);
4897 return method->slot;
4901 * mono_method_get_vtable_index:
4904 * Returns the index into the runtime vtable to access the method or,
4905 * in the case of a virtual generic method, the virtual generic method
4906 * thunk. Returns -1 on failure.
4908 * FIXME Use proper MonoError machinery here.
4911 mono_method_get_vtable_index (MonoMethod *method)
4913 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4914 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4915 if (imethod->declaring->is_generic)
4916 return mono_method_get_vtable_slot (imethod->declaring);
4918 return mono_method_get_vtable_slot (method);
4921 static MonoMethod *default_ghc = NULL;
4922 static MonoMethod *default_finalize = NULL;
4923 static int finalize_slot = -1;
4924 static int ghc_slot = -1;
4927 initialize_object_slots (MonoClass *klass)
4932 if (klass == mono_defaults.object_class) {
4933 mono_class_setup_vtable (klass);
4934 for (i = 0; i < klass->vtable_size; ++i) {
4935 MonoMethod *cm = klass->vtable [i];
4937 if (!strcmp (cm->name, "GetHashCode"))
4939 else if (!strcmp (cm->name, "Finalize"))
4943 g_assert (ghc_slot > 0);
4944 default_ghc = klass->vtable [ghc_slot];
4946 g_assert (finalize_slot > 0);
4947 default_finalize = klass->vtable [finalize_slot];
4952 MonoMethod *array_method;
4954 } GenericArrayMethodInfo;
4956 static int generic_array_method_num = 0;
4957 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4960 generic_array_methods (MonoClass *klass)
4962 int i, count_generic = 0;
4963 GList *list = NULL, *tmp;
4964 if (generic_array_method_num)
4965 return generic_array_method_num;
4966 mono_class_setup_methods (klass->parent); /*This is setting up System.Array*/
4967 g_assert (!mono_class_has_failure (klass->parent)); /*So hitting this assert is a huge problem*/
4968 for (i = 0; i < klass->parent->method.count; i++) {
4969 MonoMethod *m = klass->parent->methods [i];
4970 if (!strncmp (m->name, "InternalArray__", 15)) {
4972 list = g_list_prepend (list, m);
4975 list = g_list_reverse (list);
4976 generic_array_method_info = (GenericArrayMethodInfo *)mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4978 for (tmp = list; tmp; tmp = tmp->next) {
4979 const char *mname, *iname;
4981 MonoMethod *m = (MonoMethod *)tmp->data;
4982 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4983 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4985 generic_array_method_info [i].array_method = m;
4986 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4987 iname = "System.Collections.Generic.ICollection`1.";
4988 mname = m->name + 27;
4989 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4990 iname = "System.Collections.Generic.IEnumerable`1.";
4991 mname = m->name + 27;
4992 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4993 iname = "System.Collections.Generic.IReadOnlyList`1.";
4994 mname = m->name + strlen (ireadonlylist_prefix);
4995 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4996 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4997 mname = m->name + strlen (ireadonlycollection_prefix);
4998 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4999 iname = "System.Collections.Generic.IList`1.";
5000 mname = m->name + 15;
5002 g_assert_not_reached ();
5005 name = (gchar *)mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
5006 strcpy (name, iname);
5007 strcpy (name + strlen (iname), mname);
5008 generic_array_method_info [i].name = name;
5011 /*g_print ("array generic methods: %d\n", count_generic);*/
5013 generic_array_method_num = count_generic;
5015 return generic_array_method_num;
5019 setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos)
5021 MonoGenericContext tmp_context;
5024 tmp_context.class_inst = NULL;
5025 tmp_context.method_inst = iface->generic_class->context.class_inst;
5026 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
5028 for (i = 0; i < generic_array_method_num; i++) {
5030 MonoMethod *m = generic_array_method_info [i].array_method;
5031 MonoMethod *inflated;
5033 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
5034 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
5035 methods [pos++] = mono_marshal_get_generic_array_helper (klass, iface, generic_array_method_info [i].name, inflated);
5040 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
5042 int null_length = strlen ("(null)");
5043 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
5044 char *s = (char *)mono_image_alloc (image, len);
5047 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
5048 g_assert (result == len - 1);
5055 * @class: the class to initialize
5057 * Compute the instance_size, class_size and other infos that cannot be
5058 * computed at mono_class_get() time. Also compute vtable_size if possible.
5059 * Returns TRUE on success or FALSE if there was a problem in loading
5060 * the type (incorrect assemblies, missing assemblies, methods, etc).
5062 * LOCKING: Acquires the loader lock.
5065 mono_class_init (MonoClass *klass)
5068 MonoCachedClassInfo cached_info;
5069 gboolean has_cached_info;
5073 /* Double-checking locking pattern */
5074 if (klass->inited || mono_class_has_failure (klass))
5075 return !mono_class_has_failure (klass);
5077 /*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/
5079 /* We do everything inside the lock to prevent races */
5080 mono_loader_lock ();
5082 if (klass->inited || mono_class_has_failure (klass)) {
5083 mono_loader_unlock ();
5084 /* Somebody might have gotten in before us */
5085 return !mono_class_has_failure (klass);
5088 if (klass->init_pending) {
5089 mono_class_set_type_load_failure (klass, "Recursive type definition detected");
5093 klass->init_pending = 1;
5095 if (mono_verifier_is_enabled_for_class (klass) && !mono_verifier_verify_class (klass)) {
5096 mono_class_set_type_load_failure (klass, "%s", concat_two_strings_with_zero (klass->image, klass->name, klass->image->assembly_name));
5101 if (klass->byval_arg.type == MONO_TYPE_ARRAY || klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5102 MonoClass *element_class = klass->element_class;
5103 if (!element_class->inited)
5104 mono_class_init (element_class);
5105 if (mono_class_has_failure (element_class)) {
5106 mono_class_set_type_load_failure (klass, "");
5111 mono_stats.initialized_class_count++;
5113 if (klass->generic_class && !klass->generic_class->is_dynamic) {
5114 MonoClass *gklass = klass->generic_class->container_class;
5116 mono_stats.generic_class_count++;
5118 klass->method = gklass->method;
5119 klass->field = gklass->field;
5121 mono_class_init (gklass);
5122 // FIXME: Why is this needed ?
5123 if (!mono_class_has_failure (gklass))
5124 mono_class_setup_methods (gklass);
5125 if (mono_class_has_failure (gklass)) {
5126 mono_class_set_type_load_failure (klass, "Generic Type Defintion failed to init");
5130 if (MONO_CLASS_IS_INTERFACE (klass))
5131 klass->interface_id = mono_get_unique_iid (klass);
5134 if (klass->parent && !klass->parent->inited)
5135 mono_class_init (klass->parent);
5137 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
5139 if (klass->generic_class || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
5140 klass->nested_classes_inited = TRUE;
5143 * Computes the size used by the fields, and their locations
5145 if (has_cached_info) {
5146 klass->instance_size = cached_info.instance_size;
5147 klass->sizes.class_size = cached_info.class_size;
5148 klass->packing_size = cached_info.packing_size;
5149 klass->min_align = cached_info.min_align;
5150 klass->blittable = cached_info.blittable;
5151 klass->has_references = cached_info.has_references;
5152 klass->has_static_refs = cached_info.has_static_refs;
5153 klass->no_special_static_fields = cached_info.no_special_static_fields;
5156 if (!klass->size_inited){
5157 mono_class_setup_fields (klass);
5158 if (mono_class_has_failure (klass))
5162 /* Initialize arrays */
5164 klass->method.count = 3 + (klass->rank > 1? 2: 1);
5166 if (klass->interface_count) {
5167 int count_generic = generic_array_methods (klass);
5168 klass->method.count += klass->interface_count * count_generic;
5172 mono_class_setup_supertypes (klass);
5175 initialize_object_slots (klass);
5178 * Initialize the rest of the data without creating a generic vtable if possible.
5179 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5180 * also avoid computing a generic vtable.
5182 if (has_cached_info) {
5184 klass->vtable_size = cached_info.vtable_size;
5185 klass->has_finalize = cached_info.has_finalize;
5186 klass->has_finalize_inited = TRUE;
5187 klass->ghcimpl = cached_info.ghcimpl;
5188 klass->has_cctor = cached_info.has_cctor;
5189 } else if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5190 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5191 * The first slot if for array with.
5193 static int szarray_vtable_size[2] = { 0 };
5195 int slot = MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg) ? 0 : 1;
5198 if (!szarray_vtable_size [slot]) {
5199 mono_class_setup_vtable (klass);
5200 szarray_vtable_size [slot] = klass->vtable_size;
5202 klass->vtable_size = szarray_vtable_size[slot];
5204 } else if (klass->generic_class && !MONO_CLASS_IS_INTERFACE (klass)) {
5205 MonoClass *gklass = klass->generic_class->container_class;
5207 /* Generic instance case */
5208 klass->ghcimpl = gklass->ghcimpl;
5209 klass->has_cctor = gklass->has_cctor;
5211 mono_class_setup_vtable (gklass);
5212 if (mono_class_has_failure (gklass)) {
5213 mono_class_set_type_load_failure (klass, "");
5217 klass->vtable_size = gklass->vtable_size;
5221 /* ghcimpl is not currently used
5223 if (klass->parent) {
5224 MonoMethod *cmethod = klass->vtable [ghc_slot];
5225 if (cmethod->is_inflated)
5226 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5227 if (cmethod == default_ghc) {
5233 /* C# doesn't allow interfaces to have cctors */
5234 if (!MONO_CLASS_IS_INTERFACE (klass) || klass->image != mono_defaults.corlib) {
5235 MonoMethod *cmethod = NULL;
5237 if (klass->type_token && !image_is_dynamic(klass->image)) {
5238 cmethod = find_method_in_metadata (klass, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5239 /* The find_method function ignores the 'flags' argument */
5240 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5241 klass->has_cctor = 1;
5243 mono_class_setup_methods (klass);
5244 if (mono_class_has_failure (klass))
5247 for (i = 0; i < klass->method.count; ++i) {
5248 MonoMethod *method = klass->methods [i];
5249 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5250 (strcmp (".cctor", method->name) == 0)) {
5251 klass->has_cctor = 1;
5259 if (klass->parent) {
5260 int first_iface_slot;
5261 /* This will compute klass->parent->vtable_size for some classes */
5262 mono_class_init (klass->parent);
5263 if (mono_class_has_failure (klass->parent)) {
5264 mono_class_set_type_load_failure (klass, "");
5267 if (!klass->parent->vtable_size) {
5268 /* FIXME: Get rid of this somehow */
5269 mono_class_setup_vtable (klass->parent);
5270 if (mono_class_has_failure (klass->parent)) {
5271 mono_class_set_type_load_failure (klass, "");
5275 first_iface_slot = klass->parent->vtable_size;
5276 if (mono_class_need_stelemref_method (klass))
5278 setup_interface_offsets (klass, first_iface_slot, TRUE);
5280 setup_interface_offsets (klass, 0, TRUE);
5283 if (mono_security_core_clr_enabled ())
5284 mono_security_core_clr_check_inheritance (klass);
5286 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass))
5287 mono_class_set_type_load_failure (klass, "Invalid generic instantiation");
5292 /* Because of the double-checking locking pattern */
5293 mono_memory_barrier ();
5295 klass->init_pending = 0;
5297 mono_loader_unlock ();
5299 return !mono_class_has_failure (klass);
5303 * mono_class_has_finalizer:
5305 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5309 mono_class_has_finalizer (MonoClass *klass)
5311 gboolean has_finalize = FALSE;
5313 if (klass->has_finalize_inited)
5314 return klass->has_finalize;
5316 /* Interfaces and valuetypes are not supposed to have finalizers */
5317 if (!(MONO_CLASS_IS_INTERFACE (klass) || klass->valuetype)) {
5318 MonoMethod *cmethod = NULL;
5320 if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5321 } else if (klass->generic_class) {
5322 MonoClass *gklass = klass->generic_class->container_class;
5324 has_finalize = mono_class_has_finalizer (gklass);
5325 } else if (klass->parent && klass->parent->has_finalize) {
5326 has_finalize = TRUE;
5328 if (klass->parent) {
5330 * Can't search in metadata for a method named Finalize, because that
5331 * ignores overrides.
5333 mono_class_setup_vtable (klass);
5334 if (mono_class_has_failure (klass))
5337 cmethod = klass->vtable [finalize_slot];
5341 g_assert (klass->vtable_size > finalize_slot);
5343 if (klass->parent) {
5344 if (cmethod->is_inflated)
5345 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5346 if (cmethod != default_finalize)
5347 has_finalize = TRUE;
5353 mono_image_lock (klass->image);
5355 if (!klass->has_finalize_inited) {
5356 klass->has_finalize = has_finalize ? 1 : 0;
5358 mono_memory_barrier ();
5359 klass->has_finalize_inited = TRUE;
5362 mono_image_unlock (klass->image);
5364 return klass->has_finalize;
5368 mono_is_corlib_image (MonoImage *image)
5370 /* FIXME: allow the dynamic case for our compilers and with full trust */
5371 if (image_is_dynamic (image))
5372 return image->assembly && !strcmp (image->assembly->aname.name, "mscorlib");
5374 return image == mono_defaults.corlib;
5378 * LOCKING: this assumes the loader lock is held
5381 mono_class_setup_mono_type (MonoClass *klass)
5383 const char *name = klass->name;
5384 const char *nspace = klass->name_space;
5385 gboolean is_corlib = mono_is_corlib_image (klass->image);
5387 klass->this_arg.byref = 1;
5388 klass->this_arg.data.klass = klass;
5389 klass->this_arg.type = MONO_TYPE_CLASS;
5390 klass->byval_arg.data.klass = klass;
5391 klass->byval_arg.type = MONO_TYPE_CLASS;
5393 if (is_corlib && !strcmp (nspace, "System")) {
5394 if (!strcmp (name, "ValueType")) {
5396 * do not set the valuetype bit for System.ValueType.
5397 * klass->valuetype = 1;
5399 klass->blittable = TRUE;
5400 } else if (!strcmp (name, "Enum")) {
5402 * do not set the valuetype bit for System.Enum.
5403 * klass->valuetype = 1;
5405 klass->valuetype = 0;
5406 klass->enumtype = 0;
5407 } else if (!strcmp (name, "Object")) {
5408 klass->byval_arg.type = MONO_TYPE_OBJECT;
5409 klass->this_arg.type = MONO_TYPE_OBJECT;
5410 } else if (!strcmp (name, "String")) {
5411 klass->byval_arg.type = MONO_TYPE_STRING;
5412 klass->this_arg.type = MONO_TYPE_STRING;
5413 } else if (!strcmp (name, "TypedReference")) {
5414 klass->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5415 klass->this_arg.type = MONO_TYPE_TYPEDBYREF;
5419 if (klass->valuetype) {
5420 int t = MONO_TYPE_VALUETYPE;
5422 if (is_corlib && !strcmp (nspace, "System")) {
5425 if (!strcmp (name, "Boolean")) {
5426 t = MONO_TYPE_BOOLEAN;
5427 } else if (!strcmp(name, "Byte")) {
5429 klass->blittable = TRUE;
5433 if (!strcmp (name, "Char")) {
5438 if (!strcmp (name, "Double")) {
5440 klass->blittable = TRUE;
5444 if (!strcmp (name, "Int32")) {
5446 klass->blittable = TRUE;
5447 } else if (!strcmp(name, "Int16")) {
5449 klass->blittable = TRUE;
5450 } else if (!strcmp(name, "Int64")) {
5452 klass->blittable = TRUE;
5453 } else if (!strcmp(name, "IntPtr")) {
5455 klass->blittable = TRUE;
5459 if (!strcmp (name, "Single")) {
5461 klass->blittable = TRUE;
5462 } else if (!strcmp(name, "SByte")) {
5464 klass->blittable = TRUE;
5468 if (!strcmp (name, "UInt32")) {
5470 klass->blittable = TRUE;
5471 } else if (!strcmp(name, "UInt16")) {
5473 klass->blittable = TRUE;
5474 } else if (!strcmp(name, "UInt64")) {
5476 klass->blittable = TRUE;
5477 } else if (!strcmp(name, "UIntPtr")) {
5479 klass->blittable = TRUE;
5483 if (!strcmp (name, "TypedReference")) {
5484 t = MONO_TYPE_TYPEDBYREF;
5485 klass->blittable = TRUE;
5489 if (!strcmp (name, "Void")) {
5497 klass->byval_arg.type = (MonoTypeEnum)t;
5498 klass->this_arg.type = (MonoTypeEnum)t;
5501 if (MONO_CLASS_IS_INTERFACE (klass))
5502 klass->interface_id = mono_get_unique_iid (klass);
5508 * COM initialization is delayed until needed.
5509 * However when a [ComImport] attribute is present on a type it will trigger
5510 * the initialization. This is not a problem unless the BCL being executed
5511 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5514 init_com_from_comimport (MonoClass *klass)
5516 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5517 if (mono_security_core_clr_enabled ()) {
5518 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5519 if (!mono_security_core_clr_determine_platform_image (klass->image)) {
5520 /* but it can not be made available for application (i.e. user code) since all COM calls
5521 * are considered native calls. In this case we fail with a TypeLoadException (just like
5522 * Silverlight 2 does */
5523 mono_class_set_type_load_failure (klass, "");
5528 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5530 #endif /*DISABLE_COM*/
5533 * LOCKING: this assumes the loader lock is held
5536 mono_class_setup_parent (MonoClass *klass, MonoClass *parent)
5538 gboolean system_namespace;
5539 gboolean is_corlib = mono_is_corlib_image (klass->image);
5541 system_namespace = !strcmp (klass->name_space, "System") && is_corlib;
5543 /* if root of the hierarchy */
5544 if (system_namespace && !strcmp (klass->name, "Object")) {
5545 klass->parent = NULL;
5546 klass->instance_size = sizeof (MonoObject);
5549 if (!strcmp (klass->name, "<Module>")) {
5550 klass->parent = NULL;
5551 klass->instance_size = 0;
5555 if (!MONO_CLASS_IS_INTERFACE (klass)) {
5556 /* Imported COM Objects always derive from __ComObject. */
5558 if (MONO_CLASS_IS_IMPORT (klass)) {
5559 init_com_from_comimport (klass);
5560 if (parent == mono_defaults.object_class)
5561 parent = mono_class_get_com_object_class ();
5565 /* set the parent to something useful and safe, but mark the type as broken */
5566 parent = mono_defaults.object_class;
5567 mono_class_set_type_load_failure (klass, "");
5570 klass->parent = parent;
5572 if (parent->generic_class && !parent->name) {
5574 * If the parent is a generic instance, we may get
5575 * called before it is fully initialized, especially
5576 * before it has its name.
5581 #ifndef DISABLE_REMOTING
5582 klass->marshalbyref = parent->marshalbyref;
5583 klass->contextbound = parent->contextbound;
5586 klass->delegate = parent->delegate;
5588 if (MONO_CLASS_IS_IMPORT (klass) || mono_class_is_com_object (parent))
5589 mono_class_set_is_com_object (klass);
5591 if (system_namespace) {
5592 #ifndef DISABLE_REMOTING
5593 if (klass->name [0] == 'M' && !strcmp (klass->name, "MarshalByRefObject"))
5594 klass->marshalbyref = 1;
5596 if (klass->name [0] == 'C' && !strcmp (klass->name, "ContextBoundObject"))
5597 klass->contextbound = 1;
5599 if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate"))
5600 klass->delegate = 1;
5603 if (klass->parent->enumtype || (mono_is_corlib_image (klass->parent->image) && (strcmp (klass->parent->name, "ValueType") == 0) &&
5604 (strcmp (klass->parent->name_space, "System") == 0)))
5605 klass->valuetype = 1;
5606 if (mono_is_corlib_image (klass->parent->image) && ((strcmp (klass->parent->name, "Enum") == 0) && (strcmp (klass->parent->name_space, "System") == 0))) {
5607 klass->valuetype = klass->enumtype = 1;
5609 /*klass->enumtype = klass->parent->enumtype; */
5611 /* initialize com types if COM interfaces are present */
5613 if (MONO_CLASS_IS_IMPORT (klass))
5614 init_com_from_comimport (klass);
5616 klass->parent = NULL;
5622 * mono_class_setup_supertypes:
5625 * Build the data structure needed to make fast type checks work.
5626 * This currently sets two fields in @class:
5627 * - idepth: distance between @class and System.Object in the type
5629 * - supertypes: array of classes: each element has a class in the hierarchy
5630 * starting from @class up to System.Object
5632 * LOCKING: This function is atomic, in case of contention we waste memory.
5635 mono_class_setup_supertypes (MonoClass *klass)
5638 MonoClass **supertypes;
5640 mono_atomic_load_acquire (supertypes, MonoClass **, &klass->supertypes);
5644 if (klass->parent && !klass->parent->supertypes)
5645 mono_class_setup_supertypes (klass->parent);
5647 klass->idepth = klass->parent->idepth + 1;
5651 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, klass->idepth);
5652 supertypes = (MonoClass **)mono_class_alloc0 (klass, sizeof (MonoClass *) * ms);
5654 if (klass->parent) {
5655 CHECKED_METADATA_WRITE_PTR ( supertypes [klass->idepth - 1] , klass );
5658 for (supertype_idx = 0; supertype_idx < klass->parent->idepth; supertype_idx++)
5659 CHECKED_METADATA_WRITE_PTR ( supertypes [supertype_idx] , klass->parent->supertypes [supertype_idx] );
5661 CHECKED_METADATA_WRITE_PTR ( supertypes [0] , klass );
5664 CHECKED_METADATA_WRITE_PTR_ATOMIC ( klass->supertypes , supertypes );
5668 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5670 MonoClass *gtd = (MonoClass*)user_data;
5671 /* Only try to fix generic instances of @gtd */
5672 if (gclass->generic_class->container_class != gtd)
5675 /* Check if the generic instance has no parent. */
5676 if (gtd->parent && !gclass->parent)
5677 mono_generic_class_setup_parent (gclass, gtd);
5683 mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char *msg)
5685 mono_class_set_type_load_failure (klass, "%s", msg);
5686 mono_error_set_type_load_class (error, klass, "%s", msg);
5690 * mono_class_create_from_typedef:
5691 * @image: image where the token is valid
5692 * @type_token: typedef token
5693 * @error: used to return any error found while creating the type
5695 * Create the MonoClass* representing the specified type token.
5696 * @type_token must be a TypeDef token.
5698 * FIXME: don't return NULL on failure, just the the caller figure it out.
5701 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5703 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5704 MonoClass *klass, *parent = NULL;
5705 guint32 cols [MONO_TYPEDEF_SIZE];
5706 guint32 cols_next [MONO_TYPEDEF_SIZE];
5707 guint tidx = mono_metadata_token_index (type_token);
5708 MonoGenericContext *context = NULL;
5709 const char *name, *nspace;
5711 MonoClass **interfaces;
5712 guint32 field_last, method_last;
5713 guint32 nesting_tokeen;
5715 mono_error_init (error);
5717 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5718 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5722 mono_loader_lock ();
5724 if ((klass = (MonoClass *)mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5725 mono_loader_unlock ();
5729 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5731 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5732 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5734 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
5737 klass->name_space = nspace;
5739 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5741 klass->image = image;
5742 klass->type_token = type_token;
5743 klass->flags = cols [MONO_TYPEDEF_FLAGS];
5745 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
5747 classes_size += sizeof (MonoClass);
5750 * Check whether we're a generic type definition.
5752 klass->generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
5753 if (klass->generic_container) {
5754 klass->is_generic = 1;
5755 klass->generic_container->owner.klass = klass;
5756 klass->generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
5757 context = &klass->generic_container->context;
5760 if (klass->generic_container)
5761 enable_gclass_recording ();
5763 if (cols [MONO_TYPEDEF_EXTENDS]) {
5765 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5767 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5768 /*WARNING: this must satisfy mono_metadata_type_hash*/
5769 klass->this_arg.byref = 1;
5770 klass->this_arg.data.klass = klass;
5771 klass->this_arg.type = MONO_TYPE_CLASS;
5772 klass->byval_arg.data.klass = klass;
5773 klass->byval_arg.type = MONO_TYPE_CLASS;
5775 parent = mono_class_get_checked (image, parent_token, error);
5776 if (parent && context) /* Always inflate */
5777 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5779 if (parent == NULL) {
5780 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5781 goto parent_failure;
5784 for (tmp = parent; tmp; tmp = tmp->parent) {
5786 mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
5787 goto parent_failure;
5789 if (klass->generic_container && tmp->generic_class && tmp->generic_class->container_class == klass) {
5790 mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
5791 goto parent_failure;
5796 mono_class_setup_parent (klass, parent);
5798 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5799 mono_class_setup_mono_type (klass);
5801 if (klass->generic_container)
5802 disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
5805 * This might access klass->byval_arg for recursion generated by generic constraints,
5806 * so it has to come after setup_mono_type ().
5808 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5809 klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5810 if (!mono_error_ok (error)) {
5811 /*FIXME implement a mono_class_set_failure_from_mono_error */
5812 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5813 mono_loader_unlock ();
5814 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5819 if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5823 if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5827 klass->cast_class = klass->element_class = klass;
5829 if (!klass->enumtype) {
5830 if (!mono_metadata_interfaces_from_typedef_full (
5831 image, type_token, &interfaces, &icount, FALSE, context, error)){
5833 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5834 mono_loader_unlock ();
5835 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5839 klass->interfaces = interfaces;
5840 klass->interface_count = icount;
5841 klass->interfaces_inited = 1;
5844 /*g_print ("Load class %s\n", name);*/
5847 * Compute the field and method lists
5849 klass->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5850 klass->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5852 if (tt->rows > tidx){
5853 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5854 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5855 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5857 field_last = image->tables [MONO_TABLE_FIELD].rows;
5858 method_last = image->tables [MONO_TABLE_METHOD].rows;
5861 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5862 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5863 klass->field.count = field_last - klass->field.first;
5865 klass->field.count = 0;
5867 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5868 klass->method.count = method_last - klass->method.first;
5870 klass->method.count = 0;
5872 /* reserve space to store vector pointer in arrays */
5873 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5874 klass->instance_size += 2 * sizeof (gpointer);
5875 g_assert (klass->field.count == 0);
5878 if (klass->enumtype) {
5879 MonoType *enum_basetype = mono_class_find_enum_basetype (klass, error);
5880 if (!enum_basetype) {
5881 /*set it to a default value as the whole runtime can't handle this to be null*/
5882 klass->cast_class = klass->element_class = mono_defaults.int32_class;
5883 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5884 mono_loader_unlock ();
5885 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5888 klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
5892 * If we're a generic type definition, load the constraints.
5893 * We must do this after the class has been constructed to make certain recursive scenarios
5896 if (klass->generic_container && !mono_metadata_load_generic_param_constraints_checked (image, type_token, klass->generic_container, error)) {
5897 mono_class_set_type_load_failure (klass, "Could not load generic parameter constrains due to %s", mono_error_get_message (error));
5898 mono_loader_unlock ();
5899 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5903 if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5904 if (!strncmp (name, "Vector", 6))
5905 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");
5908 mono_loader_unlock ();
5910 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5915 mono_class_setup_mono_type (klass);
5916 mono_loader_unlock ();
5917 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5921 /** Is klass a Nullable<T> ginst? */
5923 mono_class_is_nullable (MonoClass *klass)
5925 return klass->generic_class != NULL &&
5926 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5930 /** if klass is T? return T */
5932 mono_class_get_nullable_param (MonoClass *klass)
5934 g_assert (mono_class_is_nullable (klass));
5935 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5939 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5943 MonoGenericClass *gclass = klass->generic_class;
5945 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5946 if (!mono_error_ok (&error)) {
5947 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5948 klass->parent = mono_defaults.object_class;
5949 mono_class_set_type_load_failure (klass, "");
5950 mono_error_cleanup (&error);
5954 mono_class_setup_parent (klass, klass->parent);
5956 if (klass->enumtype) {
5957 klass->cast_class = gtd->cast_class;
5958 klass->element_class = gtd->element_class;
5964 * Create the `MonoClass' for an instantiation of a generic type.
5965 * We only do this if we actually need it.
5968 mono_generic_class_get_class (MonoGenericClass *gclass)
5970 MonoClass *klass, *gklass;
5972 if (gclass->cached_class)
5973 return gclass->cached_class;
5975 mono_loader_lock ();
5976 if (gclass->cached_class) {
5977 mono_loader_unlock ();
5978 return gclass->cached_class;
5981 klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
5983 gklass = gclass->container_class;
5985 if (record_gclass_instantiation > 0)
5986 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
5988 if (gklass->nested_in) {
5989 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
5990 klass->nested_in = gklass->nested_in;
5993 klass->name = gklass->name;
5994 klass->name_space = gklass->name_space;
5996 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5998 klass->image = gklass->image;
5999 klass->flags = gklass->flags;
6000 klass->type_token = gklass->type_token;
6001 klass->field.count = gklass->field.count;
6003 klass->is_inflated = 1;
6004 klass->generic_class = gclass;
6006 klass->byval_arg.type = MONO_TYPE_GENERICINST;
6007 klass->this_arg.type = klass->byval_arg.type;
6008 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
6009 klass->this_arg.byref = TRUE;
6010 klass->enumtype = gklass->enumtype;
6011 klass->valuetype = gklass->valuetype;
6013 klass->cast_class = klass->element_class = klass;
6015 if (mono_class_is_nullable (klass))
6016 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
6019 * We're not interested in the nested classes of a generic instance.
6020 * We use the generic type definition to look for nested classes.
6023 mono_generic_class_setup_parent (klass, gklass);
6025 if (gclass->is_dynamic) {
6027 * 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.
6028 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
6029 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
6031 if (!gklass->wastypebuilder)
6034 mono_class_setup_supertypes (klass);
6036 if (klass->enumtype) {
6038 * For enums, gklass->fields might not been set, but instance_size etc. is
6039 * already set in mono_reflection_create_internal_class (). For non-enums,
6040 * these will be computed normally in mono_class_layout_fields ().
6042 klass->instance_size = gklass->instance_size;
6043 klass->sizes.class_size = gklass->sizes.class_size;
6044 mono_memory_barrier ();
6045 klass->size_inited = 1;
6049 mono_memory_barrier ();
6050 gclass->cached_class = klass;
6052 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6054 inflated_classes ++;
6055 inflated_classes_size += sizeof (MonoClass);
6057 mono_loader_unlock ();
6063 get_image_for_container (MonoGenericContainer *container)
6066 if (container->is_anonymous) {
6067 result = container->owner.image;
6070 if (container->is_method) {
6071 MonoMethod *method = container->owner.method;
6072 g_assert_checked (method);
6073 klass = method->klass;
6075 klass = container->owner.klass;
6077 g_assert_checked (klass);
6078 result = klass->image;
6085 get_image_for_generic_param (MonoGenericParam *param)
6087 MonoGenericContainer *container = mono_generic_param_owner (param);
6088 g_assert_checked (container);
6089 return get_image_for_container (container);
6092 // Make a string in the designated image consisting of a single integer.
6093 #define INT_STRING_SIZE 16
6095 make_generic_name_string (MonoImage *image, int num)
6097 char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
6098 g_snprintf (name, INT_STRING_SIZE, "%d", num);
6102 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
6103 // pinfo is derived from param by the caller for us.
6105 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
6107 MonoClass *klass, **ptr;
6109 MonoGenericContainer *container = mono_generic_param_owner (param);
6110 g_assert_checked (container);
6112 MonoImage *image = get_image_for_container (container);
6113 gboolean is_mvar = container->is_method;
6114 gboolean is_anonymous = container->is_anonymous;
6116 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6117 classes_size += sizeof (MonoClass);
6120 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
6122 int n = mono_generic_param_num (param);
6123 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
6127 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , "" );
6128 } else if (is_mvar) {
6129 MonoMethod *omethod = container->owner.method;
6130 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
6132 MonoClass *oklass = container->owner.klass;
6133 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
6136 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6138 // Count non-NULL items in pinfo->constraints
6141 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6145 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6146 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
6148 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
6149 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
6151 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
6154 if (count - pos > 0) {
6155 klass->interface_count = count - pos;
6156 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
6157 klass->interfaces_inited = TRUE;
6158 for (i = pos; i < count; i++)
6159 CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
6162 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
6164 klass->inited = TRUE;
6165 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class , klass );
6166 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
6167 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
6169 klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6170 klass->this_arg.type = klass->byval_arg.type;
6171 CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param , param );
6172 CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
6173 klass->this_arg.byref = TRUE;
6175 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6176 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6178 /*Init these fields to sane values*/
6179 klass->min_align = 1;
6181 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6182 * constrained to, the JIT depends on this.
6184 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6185 mono_memory_barrier ();
6186 klass->size_inited = 1;
6187 klass->setup_fields_called = 1;
6189 mono_class_setup_supertypes (klass);
6191 if (count - pos > 0) {
6192 mono_class_setup_vtable (klass->parent);
6193 if (mono_class_has_failure (klass->parent))
6194 mono_class_set_type_load_failure (klass, "Failed to setup parent interfaces");
6196 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6202 #define FAST_CACHE_SIZE 16
6205 * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6206 * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6207 * we cache the MonoClasses.
6208 * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6209 * LOCKING: Takes the image lock depending on @take_lock.
6212 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6214 int n = mono_generic_param_num (param);
6215 MonoImage *image = get_image_for_generic_param (param);
6216 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6217 MonoClass *klass = NULL;
6222 // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6223 // For high numbers or constraints we have to use pointer hashes.
6224 if (param->gshared_constraint) {
6225 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6228 mono_image_lock (image);
6229 klass = (MonoClass *)g_hash_table_lookup (ht, param);
6231 mono_image_unlock (image);
6236 if (n < FAST_CACHE_SIZE) {
6238 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6240 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6242 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6245 mono_image_lock (image);
6246 klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6248 mono_image_unlock (image);
6255 * LOCKING: Image lock (param->image) must be held
6258 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6260 int n = mono_generic_param_num (param);
6261 MonoImage *image = get_image_for_generic_param (param);
6262 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6266 if (param->gshared_constraint) {
6267 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6269 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6270 mono_memory_barrier ();
6272 image->mvar_cache_constrained = ht;
6274 image->var_cache_constrained = ht;
6276 g_hash_table_insert (ht, param, klass);
6277 } else if (n < FAST_CACHE_SIZE) {
6279 /* Requires locking to avoid droping an already published class */
6280 if (!image->mvar_cache_fast)
6281 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6282 image->mvar_cache_fast [n] = klass;
6284 if (!image->var_cache_fast)
6285 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6286 image->var_cache_fast [n] = klass;
6289 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6291 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6293 ht = g_hash_table_new (NULL, NULL);
6294 mono_memory_barrier ();
6296 image->mvar_cache_slow = ht;
6298 image->var_cache_slow = ht;
6301 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6306 * LOCKING: Acquires the image lock (@image).
6309 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6311 MonoImage *image = get_image_for_generic_param (param);
6312 MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6313 MonoClass *klass, *klass2;
6315 // If a klass already exists for this object and is cached, return it.
6316 if (pinfo) // Non-anonymous
6317 klass = pinfo->pklass;
6319 klass = get_anon_gparam_class (param, TRUE);
6324 // Create a new klass
6325 klass = make_generic_param_class (param, pinfo);
6327 // Now we need to cache the klass we created.
6328 // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6329 // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6330 // and allow our newly-created klass object to just leak.
6331 mono_memory_barrier ();
6333 mono_image_lock (image);
6335 // Here "klass2" refers to the klass potentially created by the other thread.
6336 if (pinfo) // Repeat check from above
6337 klass2 = pinfo->pklass;
6339 klass2 = get_anon_gparam_class (param, FALSE);
6346 pinfo->pklass = klass;
6348 set_anon_gparam_class (param, klass);
6350 mono_image_unlock (image);
6352 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6354 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED); // Alert profiler about botched class create
6356 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6362 * mono_class_from_generic_parameter:
6363 * @param: Parameter to find/construct a class for.
6364 * @arg2: Is ignored.
6365 * @arg3: Is ignored.
6368 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6370 return mono_class_from_generic_parameter_internal (param);
6375 mono_ptr_class_get (MonoType *type)
6378 MonoClass *el_class;
6382 el_class = mono_class_from_mono_type (type);
6383 image = el_class->image;
6385 mono_image_lock (image);
6386 if (image->ptr_cache) {
6387 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6388 mono_image_unlock (image);
6392 mono_image_unlock (image);
6394 result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6396 classes_size += sizeof (MonoClass);
6398 result->parent = NULL; /* no parent for PTR types */
6399 result->name_space = el_class->name_space;
6400 name = g_strdup_printf ("%s*", el_class->name);
6401 result->name = mono_image_strdup (image, name);
6404 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6406 result->image = el_class->image;
6407 result->inited = TRUE;
6408 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6409 /* Can pointers get boxed? */
6410 result->instance_size = sizeof (gpointer);
6411 result->cast_class = result->element_class = el_class;
6412 result->blittable = TRUE;
6414 result->byval_arg.type = MONO_TYPE_PTR;
6415 result->this_arg.type = result->byval_arg.type;
6416 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6417 result->this_arg.byref = TRUE;
6419 mono_class_setup_supertypes (result);
6421 mono_image_lock (image);
6422 if (image->ptr_cache) {
6424 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6425 mono_image_unlock (image);
6426 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6430 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6432 g_hash_table_insert (image->ptr_cache, el_class, result);
6433 mono_image_unlock (image);
6435 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6441 mono_fnptr_class_get (MonoMethodSignature *sig)
6444 static GHashTable *ptr_hash = NULL;
6446 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6448 mono_loader_lock ();
6451 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6453 if ((result = (MonoClass *)g_hash_table_lookup (ptr_hash, sig))) {
6454 mono_loader_unlock ();
6457 result = g_new0 (MonoClass, 1);
6459 result->parent = NULL; /* no parent for PTR types */
6460 result->name_space = "System";
6461 result->name = "MonoFNPtrFakeClass";
6463 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6465 result->image = mono_defaults.corlib; /* need to fix... */
6466 result->inited = TRUE;
6467 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6468 /* Can pointers get boxed? */
6469 result->instance_size = sizeof (gpointer);
6470 result->cast_class = result->element_class = result;
6471 result->blittable = TRUE;
6473 result->byval_arg.type = MONO_TYPE_FNPTR;
6474 result->this_arg.type = result->byval_arg.type;
6475 result->this_arg.data.method = result->byval_arg.data.method = sig;
6476 result->this_arg.byref = TRUE;
6477 result->blittable = TRUE;
6479 mono_class_setup_supertypes (result);
6481 g_hash_table_insert (ptr_hash, sig, result);
6483 mono_loader_unlock ();
6485 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6491 * mono_class_from_mono_type:
6492 * @type: describes the type to return
6494 * This returns a MonoClass for the specified MonoType, the value is never NULL.
6497 mono_class_from_mono_type (MonoType *type)
6499 switch (type->type) {
6500 case MONO_TYPE_OBJECT:
6501 return type->data.klass? type->data.klass: mono_defaults.object_class;
6502 case MONO_TYPE_VOID:
6503 return type->data.klass? type->data.klass: mono_defaults.void_class;
6504 case MONO_TYPE_BOOLEAN:
6505 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6506 case MONO_TYPE_CHAR:
6507 return type->data.klass? type->data.klass: mono_defaults.char_class;
6509 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6511 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6513 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6515 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6517 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6519 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6521 return type->data.klass? type->data.klass: mono_defaults.int_class;
6523 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6525 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6527 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6529 return type->data.klass? type->data.klass: mono_defaults.single_class;
6531 return type->data.klass? type->data.klass: mono_defaults.double_class;
6532 case MONO_TYPE_STRING:
6533 return type->data.klass? type->data.klass: mono_defaults.string_class;
6534 case MONO_TYPE_TYPEDBYREF:
6535 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6536 case MONO_TYPE_ARRAY:
6537 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6539 return mono_ptr_class_get (type->data.type);
6540 case MONO_TYPE_FNPTR:
6541 return mono_fnptr_class_get (type->data.method);
6542 case MONO_TYPE_SZARRAY:
6543 return mono_array_class_get (type->data.klass, 1);
6544 case MONO_TYPE_CLASS:
6545 case MONO_TYPE_VALUETYPE:
6546 return type->data.klass;
6547 case MONO_TYPE_GENERICINST:
6548 return mono_generic_class_get_class (type->data.generic_class);
6549 case MONO_TYPE_MVAR:
6551 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6553 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6554 g_assert_not_reached ();
6557 // Yes, this returns NULL, even if it is documented as not doing so, but there
6558 // is no way for the code to make it this far, due to the assert above.
6563 * mono_type_retrieve_from_typespec
6564 * @image: context where the image is created
6565 * @type_spec: typespec token
6566 * @context: the generic context used to evaluate generic instantiations in
6569 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6571 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6573 *did_inflate = FALSE;
6578 if (context && (context->class_inst || context->method_inst)) {
6579 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6581 if (!mono_error_ok (error)) {
6587 *did_inflate = TRUE;
6594 * mono_class_create_from_typespec
6595 * @image: context where the image is created
6596 * @type_spec: typespec token
6597 * @context: the generic context used to evaluate generic instantiations in
6600 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6603 gboolean inflated = FALSE;
6604 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6605 return_val_if_nok (error, NULL);
6606 ret = mono_class_from_mono_type (t);
6608 mono_metadata_free_type (t);
6613 * mono_bounded_array_class_get:
6614 * @element_class: element class
6615 * @rank: the dimension of the array class
6616 * @bounded: whenever the array has non-zero bounds
6618 * Returns: A class object describing the array with element type @element_type and
6622 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6626 MonoClass *parent = NULL;
6627 GSList *list, *rootlist = NULL;
6630 gboolean corlib_type = FALSE;
6632 g_assert (rank <= 255);
6635 /* bounded only matters for one-dimensional arrays */
6638 image = eclass->image;
6640 if (rank == 1 && !bounded) {
6642 * This case is very frequent not just during compilation because of calls
6643 * from mono_class_from_mono_type (), mono_array_new (),
6644 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6646 mono_os_mutex_lock (&image->szarray_cache_lock);
6647 if (!image->szarray_cache)
6648 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6649 klass = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6650 mono_os_mutex_unlock (&image->szarray_cache_lock);
6654 mono_loader_lock ();
6656 mono_loader_lock ();
6658 if (!image->array_cache)
6659 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6661 if ((rootlist = list = (GSList *)g_hash_table_lookup (image->array_cache, eclass))) {
6662 for (; list; list = list->next) {
6663 klass = (MonoClass *)list->data;
6664 if ((klass->rank == rank) && (klass->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6665 mono_loader_unlock ();
6672 /* for the building corlib use System.Array from it */
6673 if (image->assembly && assembly_is_dynamic (image->assembly) && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6674 parent = mono_class_load_from_name (image, "System", "Array");
6677 parent = mono_defaults.array_class;
6678 if (!parent->inited)
6679 mono_class_init (parent);
6682 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6684 klass->image = image;
6685 klass->name_space = eclass->name_space;
6686 nsize = strlen (eclass->name);
6687 name = (char *)g_malloc (nsize + 2 + rank + 1);
6688 memcpy (name, eclass->name, nsize);
6691 memset (name + nsize + 1, ',', rank - 1);
6693 name [nsize + rank] = '*';
6694 name [nsize + rank + bounded] = ']';
6695 name [nsize + rank + bounded + 1] = 0;
6696 klass->name = mono_image_strdup (image, name);
6699 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6701 classes_size += sizeof (MonoClass);
6703 klass->type_token = 0;
6704 /* all arrays are marked serializable and sealed, bug #42779 */
6705 klass->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6706 klass->parent = parent;
6707 klass->instance_size = mono_class_instance_size (klass->parent);
6709 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6710 /*Arrays of those two types are invalid.*/
6711 MonoError prepared_error;
6712 mono_error_init (&prepared_error);
6713 mono_error_set_invalid_program (&prepared_error, "Arrays of void or System.TypedReference types are invalid.");
6714 mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6715 mono_error_cleanup (&prepared_error);
6716 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6717 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6718 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6719 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6721 /* element_size -1 is ok as this is not an instantitable type*/
6722 klass->sizes.element_size = -1;
6724 klass->sizes.element_size = mono_class_array_element_size (eclass);
6726 mono_class_setup_supertypes (klass);
6728 if (eclass->generic_class)
6729 mono_class_init (eclass);
6730 if (!eclass->size_inited)
6731 mono_class_setup_fields (eclass);
6732 if (mono_class_has_failure (eclass)) /*FIXME we fail the array type, but we have to let other fields be set.*/
6733 mono_class_set_type_load_failure (klass, "");
6735 klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6739 if (eclass->enumtype)
6740 klass->cast_class = eclass->element_class;
6742 klass->cast_class = eclass;
6744 switch (klass->cast_class->byval_arg.type) {
6746 klass->cast_class = mono_defaults.byte_class;
6749 klass->cast_class = mono_defaults.int16_class;
6752 #if SIZEOF_VOID_P == 4
6756 klass->cast_class = mono_defaults.int32_class;
6759 #if SIZEOF_VOID_P == 8
6763 klass->cast_class = mono_defaults.int64_class;
6769 klass->element_class = eclass;
6771 if ((rank > 1) || bounded) {
6772 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6773 klass->byval_arg.type = MONO_TYPE_ARRAY;
6774 klass->byval_arg.data.array = at;
6775 at->eklass = eclass;
6777 /* FIXME: complete.... */
6779 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6780 klass->byval_arg.data.klass = eclass;
6782 klass->this_arg = klass->byval_arg;
6783 klass->this_arg.byref = 1;
6788 klass->generic_container = eclass->generic_container;
6790 if (rank == 1 && !bounded) {
6791 MonoClass *prev_class;
6793 mono_os_mutex_lock (&image->szarray_cache_lock);
6794 prev_class = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6796 /* Someone got in before us */
6799 g_hash_table_insert (image->szarray_cache, eclass, klass);
6800 mono_os_mutex_unlock (&image->szarray_cache_lock);
6802 list = g_slist_append (rootlist, klass);
6803 g_hash_table_insert (image->array_cache, eclass, list);
6806 mono_loader_unlock ();
6808 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6814 * mono_array_class_get:
6815 * @element_class: element class
6816 * @rank: the dimension of the array class
6818 * Returns: A class object describing the array with element type @element_type and
6822 mono_array_class_get (MonoClass *eclass, guint32 rank)
6824 return mono_bounded_array_class_get (eclass, rank, FALSE);
6828 * mono_class_instance_size:
6831 * Use to get the size of a class in bytes.
6833 * Returns: The size of an object instance
6836 mono_class_instance_size (MonoClass *klass)
6838 if (!klass->size_inited)
6839 mono_class_init (klass);
6841 return klass->instance_size;
6845 * mono_class_min_align:
6848 * Use to get the computed minimum alignment requirements for the specified class.
6850 * Returns: minimm alignment requirements
6853 mono_class_min_align (MonoClass *klass)
6855 if (!klass->size_inited)
6856 mono_class_init (klass);
6858 return klass->min_align;
6862 * mono_class_value_size:
6865 * This function is used for value types, and return the
6866 * space and the alignment to store that kind of value object.
6868 * Returns: the size of a value of kind @klass
6871 mono_class_value_size (MonoClass *klass, guint32 *align)
6875 /* fixme: check disable, because we still have external revereces to
6876 * mscorlib and Dummy Objects
6878 /*g_assert (klass->valuetype);*/
6880 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6883 *align = klass->min_align;
6889 * mono_class_data_size:
6892 * Returns: The size of the static class data
6895 mono_class_data_size (MonoClass *klass)
6898 mono_class_init (klass);
6899 /* This can happen with dynamically created types */
6900 if (!klass->fields_inited)
6901 mono_class_setup_fields_locking (klass);
6903 /* in arrays, sizes.class_size is unioned with element_size
6904 * and arrays have no static fields
6908 return klass->sizes.class_size;
6912 * Auxiliary routine to mono_class_get_field
6914 * Takes a field index instead of a field token.
6916 static MonoClassField *
6917 mono_class_get_field_idx (MonoClass *klass, int idx)
6919 mono_class_setup_fields_locking (klass);
6920 if (mono_class_has_failure (klass))
6924 if (klass->image->uncompressed_metadata) {
6926 * klass->field.first points to the FieldPtr table, while idx points into the
6927 * Field table, so we have to do a search.
6929 /*FIXME this is broken for types with multiple fields with the same name.*/
6930 const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6933 for (i = 0; i < klass->field.count; ++i)
6934 if (mono_field_get_name (&klass->fields [i]) == name)
6935 return &klass->fields [i];
6936 g_assert_not_reached ();
6938 if (klass->field.count) {
6939 if ((idx >= klass->field.first) && (idx < klass->field.first + klass->field.count)){
6940 return &klass->fields [idx - klass->field.first];
6944 klass = klass->parent;
6950 * mono_class_get_field:
6951 * @class: the class to lookup the field.
6952 * @field_token: the field token
6954 * Returns: A MonoClassField representing the type and offset of
6955 * the field, or a NULL value if the field does not belong to this
6959 mono_class_get_field (MonoClass *klass, guint32 field_token)
6961 int idx = mono_metadata_token_index (field_token);
6963 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6965 return mono_class_get_field_idx (klass, idx - 1);
6969 * mono_class_get_field_from_name:
6970 * @klass: the class to lookup the field.
6971 * @name: the field name
6973 * Search the class @klass and it's parents for a field with the name @name.
6975 * Returns: The MonoClassField pointer of the named field or NULL
6978 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6980 return mono_class_get_field_from_name_full (klass, name, NULL);
6984 * mono_class_get_field_from_name_full:
6985 * @klass: the class to lookup the field.
6986 * @name: the field name
6987 * @type: the type of the fields. This optional.
6989 * Search the class @klass and it's parents for a field with the name @name and type @type.
6991 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
6992 * of its generic type definition.
6994 * Returns: The MonoClassField pointer of the named field or NULL
6997 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
7001 mono_class_setup_fields_locking (klass);
7002 if (mono_class_has_failure (klass))
7006 for (i = 0; i < klass->field.count; ++i) {
7007 MonoClassField *field = &klass->fields [i];
7009 if (strcmp (name, mono_field_get_name (field)) != 0)
7013 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
7014 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
7019 klass = klass->parent;
7025 * mono_class_get_field_token:
7026 * @field: the field we need the token of
7028 * Get the token of a field. Note that the tokesn is only valid for the image
7029 * the field was loaded from. Don't use this function for fields in dynamic types.
7031 * Returns: The token representing the field in the image it was loaded from.
7034 mono_class_get_field_token (MonoClassField *field)
7036 MonoClass *klass = field->parent;
7039 mono_class_setup_fields_locking (klass);
7044 for (i = 0; i < klass->field.count; ++i) {
7045 if (&klass->fields [i] == field) {
7046 int idx = klass->field.first + i + 1;
7048 if (klass->image->uncompressed_metadata)
7049 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
7050 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
7053 klass = klass->parent;
7056 g_assert_not_reached ();
7061 mono_field_get_index (MonoClassField *field)
7063 int index = field - field->parent->fields;
7065 g_assert (index >= 0 && index < field->parent->field.count);
7071 * mono_class_get_field_default_value:
7073 * Return the default value of the field as a pointer into the metadata blob.
7076 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
7079 guint32 constant_cols [MONO_CONSTANT_SIZE];
7081 MonoClass *klass = field->parent;
7083 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7085 if (!klass->ext || !klass->ext->field_def_values) {
7086 MonoFieldDefaultValue *def_values;
7088 mono_class_alloc_ext (klass);
7090 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
7092 mono_image_lock (klass->image);
7093 mono_memory_barrier ();
7094 if (!klass->ext->field_def_values)
7095 klass->ext->field_def_values = def_values;
7096 mono_image_unlock (klass->image);
7099 field_index = mono_field_get_index (field);
7101 if (!klass->ext->field_def_values [field_index].data) {
7102 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7106 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7108 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7109 klass->ext->field_def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7110 klass->ext->field_def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7113 *def_type = klass->ext->field_def_values [field_index].def_type;
7114 return klass->ext->field_def_values [field_index].data;
7118 mono_property_get_index (MonoProperty *prop)
7120 int index = prop - prop->parent->ext->properties;
7122 g_assert (index >= 0 && index < prop->parent->ext->property.count);
7128 * mono_class_get_property_default_value:
7130 * Return the default value of the field as a pointer into the metadata blob.
7133 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7136 guint32 constant_cols [MONO_CONSTANT_SIZE];
7137 MonoClass *klass = property->parent;
7139 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7141 * We don't cache here because it is not used by C# so it's quite rare, but
7142 * we still do the lookup in klass->ext because that is where the data
7143 * is stored for dynamic assemblies.
7146 if (image_is_dynamic (klass->image)) {
7147 int prop_index = mono_property_get_index (property);
7148 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
7149 *def_type = klass->ext->prop_def_values [prop_index].def_type;
7150 return klass->ext->prop_def_values [prop_index].data;
7154 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7158 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7159 *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7160 return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7164 mono_class_get_event_token (MonoEvent *event)
7166 MonoClass *klass = event->parent;
7171 for (i = 0; i < klass->ext->event.count; ++i) {
7172 if (&klass->ext->events [i] == event)
7173 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
7176 klass = klass->parent;
7179 g_assert_not_reached ();
7184 * mono_class_get_property_from_name:
7186 * @name: name of the property to lookup in the specified class
7188 * Use this method to lookup a property in a class
7189 * Returns: the MonoProperty with the given name, or NULL if the property
7190 * does not exist on the @klass.
7193 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7197 gpointer iter = NULL;
7198 while ((p = mono_class_get_properties (klass, &iter))) {
7199 if (! strcmp (name, p->name))
7202 klass = klass->parent;
7208 * mono_class_get_property_token:
7209 * @prop: MonoProperty to query
7211 * Returns: The ECMA token for the specified property.
7214 mono_class_get_property_token (MonoProperty *prop)
7216 MonoClass *klass = prop->parent;
7220 gpointer iter = NULL;
7221 while ((p = mono_class_get_properties (klass, &iter))) {
7222 if (&klass->ext->properties [i] == prop)
7223 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
7227 klass = klass->parent;
7230 g_assert_not_reached ();
7235 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7237 const char *name, *nspace;
7238 if (image_is_dynamic (image))
7239 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7241 switch (type_token & 0xff000000){
7242 case MONO_TOKEN_TYPE_DEF: {
7243 guint32 cols [MONO_TYPEDEF_SIZE];
7244 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7245 guint tidx = mono_metadata_token_index (type_token);
7247 if (tidx > tt->rows)
7248 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7250 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7251 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7252 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7253 if (strlen (nspace) == 0)
7254 return g_strdup_printf ("%s", name);
7256 return g_strdup_printf ("%s.%s", nspace, name);
7259 case MONO_TOKEN_TYPE_REF: {
7261 guint32 cols [MONO_TYPEREF_SIZE];
7262 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7263 guint tidx = mono_metadata_token_index (type_token);
7266 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7268 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7269 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7270 mono_error_cleanup (&error);
7274 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7275 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7276 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7277 if (strlen (nspace) == 0)
7278 return g_strdup_printf ("%s", name);
7280 return g_strdup_printf ("%s.%s", nspace, name);
7283 case MONO_TOKEN_TYPE_SPEC:
7284 return g_strdup_printf ("Typespec 0x%08x", type_token);
7286 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7291 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7293 if (image_is_dynamic (image))
7294 return g_strdup_printf ("DynamicAssembly %s", image->name);
7296 switch (type_token & 0xff000000){
7297 case MONO_TOKEN_TYPE_DEF:
7298 if (image->assembly)
7299 return mono_stringify_assembly_name (&image->assembly->aname);
7300 else if (image->assembly_name)
7301 return g_strdup (image->assembly_name);
7302 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7303 case MONO_TOKEN_TYPE_REF: {
7305 MonoAssemblyName aname;
7306 guint32 cols [MONO_TYPEREF_SIZE];
7307 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7308 guint32 idx = mono_metadata_token_index (type_token);
7311 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7313 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7314 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7315 mono_error_cleanup (&error);
7318 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7320 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7321 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7322 case MONO_RESOLUTION_SCOPE_MODULE:
7324 return g_strdup ("");
7325 case MONO_RESOLUTION_SCOPE_MODULEREF:
7327 return g_strdup ("");
7328 case MONO_RESOLUTION_SCOPE_TYPEREF:
7330 return g_strdup ("");
7331 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7332 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7333 return mono_stringify_assembly_name (&aname);
7335 g_assert_not_reached ();
7339 case MONO_TOKEN_TYPE_SPEC:
7341 return g_strdup ("");
7343 g_assert_not_reached ();
7350 * mono_class_get_full:
7351 * @image: the image where the class resides
7352 * @type_token: the token for the class
7353 * @context: the generic context used to evaluate generic instantiations in
7354 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7356 * Returns: The MonoClass that represents @type_token in @image
7359 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7363 klass = mono_class_get_checked (image, type_token, &error);
7365 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7366 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7368 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7374 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7378 mono_error_init (error);
7379 klass = mono_class_get_checked (image, type_token, error);
7381 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7382 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7387 * mono_class_get_checked:
7388 * @image: the image where the class resides
7389 * @type_token: the token for the class
7390 * @error: error object to return any error
7392 * Returns: The MonoClass that represents @type_token in @image, or NULL on error.
7395 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7397 MonoClass *klass = NULL;
7399 mono_error_init (error);
7401 if (image_is_dynamic (image)) {
7402 int table = mono_metadata_token_table (type_token);
7404 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7405 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7408 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
7412 switch (type_token & 0xff000000){
7413 case MONO_TOKEN_TYPE_DEF:
7414 klass = mono_class_create_from_typedef (image, type_token, error);
7416 case MONO_TOKEN_TYPE_REF:
7417 klass = mono_class_from_typeref_checked (image, type_token, error);
7419 case MONO_TOKEN_TYPE_SPEC:
7420 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7423 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7427 /* Generic case, should be avoided for when a better error is possible. */
7428 if (!klass && mono_error_ok (error)) {
7429 char *name = mono_class_name_from_token (image, type_token);
7430 char *assembly = mono_assembly_name_from_token (image, type_token);
7431 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7439 * mono_type_get_checked:
7440 * @image: the image where the type resides
7441 * @type_token: the token for the type
7442 * @context: the generic context used to evaluate generic instantiations in
7443 * @error: Error handling context
7445 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7447 * Returns: The MonoType that represents @type_token in @image
7450 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7452 MonoType *type = NULL;
7453 gboolean inflated = FALSE;
7455 mono_error_init (error);
7457 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7458 if (image_is_dynamic (image)) {
7459 MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
7460 return_val_if_nok (error, NULL);
7461 return mono_class_get_type (klass);
7464 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7465 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7472 return mono_class_get_type (klass);
7475 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7482 MonoType *tmp = type;
7483 type = mono_class_get_type (mono_class_from_mono_type (type));
7484 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7485 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7486 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7488 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7490 if (type->type != tmp->type)
7493 mono_metadata_free_type (tmp);
7500 * @image: image where the class token will be looked up.
7501 * @type_token: a type token from the image
7503 * Returns the MonoClass with the given @type_token on the @image
7506 mono_class_get (MonoImage *image, guint32 type_token)
7508 return mono_class_get_full (image, type_token, NULL);
7512 * mono_image_init_name_cache:
7514 * Initializes the class name cache stored in image->name_cache.
7516 * LOCKING: Acquires the corresponding image lock.
7519 mono_image_init_name_cache (MonoImage *image)
7521 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7522 guint32 cols [MONO_TYPEDEF_SIZE];
7525 guint32 i, visib, nspace_index;
7526 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7528 if (image->name_cache)
7531 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7533 if (image_is_dynamic (image)) {
7534 mono_image_lock (image);
7535 if (image->name_cache) {
7536 /* Somebody initialized it before us */
7537 g_hash_table_destroy (the_name_cache);
7539 mono_atomic_store_release (&image->name_cache, the_name_cache);
7541 mono_image_unlock (image);
7545 /* Temporary hash table to avoid lookups in the nspace_table */
7546 name_cache2 = g_hash_table_new (NULL, NULL);
7548 for (i = 1; i <= t->rows; ++i) {
7549 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7550 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7552 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7553 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7555 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7557 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7558 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7560 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7561 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7562 if (!nspace_table) {
7563 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7564 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7565 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7568 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7571 /* Load type names from EXPORTEDTYPES table */
7573 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7574 guint32 cols [MONO_EXP_TYPE_SIZE];
7577 for (i = 0; i < t->rows; ++i) {
7578 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7580 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7581 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7585 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7586 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7588 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7589 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7590 if (!nspace_table) {
7591 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7592 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7593 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7596 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7600 g_hash_table_destroy (name_cache2);
7602 mono_image_lock (image);
7603 if (image->name_cache) {
7604 /* Somebody initialized it before us */
7605 g_hash_table_destroy (the_name_cache);
7607 mono_atomic_store_release (&image->name_cache, the_name_cache);
7609 mono_image_unlock (image);
7612 /*FIXME Only dynamic assemblies should allow this operation.*/
7614 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7615 const char *name, guint32 index)
7617 GHashTable *nspace_table;
7618 GHashTable *name_cache;
7621 mono_image_init_name_cache (image);
7622 mono_image_lock (image);
7624 name_cache = image->name_cache;
7625 if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7626 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7627 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7630 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7631 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7633 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7635 mono_image_unlock (image);
7644 find_nocase (gpointer key, gpointer value, gpointer user_data)
7646 char *name = (char*)key;
7647 FindUserData *data = (FindUserData*)user_data;
7649 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7650 data->value = value;
7654 * mono_class_from_name_case:
7655 * @image: The MonoImage where the type is looked up in
7656 * @name_space: the type namespace
7657 * @name: the type short name.
7658 * @deprecated: use the mono_class_from_name_case_checked variant instead.
7660 * Obtains a MonoClass with a given namespace and a given name which
7661 * is located in the given MonoImage. The namespace and name
7662 * lookups are case insensitive.
7665 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7668 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7669 mono_error_cleanup (&error);
7675 * mono_class_from_name_case:
7676 * @image: The MonoImage where the type is looked up in
7677 * @name_space: the type namespace
7678 * @name: the type short name.
7681 * Obtains a MonoClass with a given namespace and a given name which
7682 * is located in the given MonoImage. The namespace and name
7683 * lookups are case insensitive.
7685 * Returns: The MonoClass if the given namespace and name were found, or NULL if it
7686 * was not found. The @error object will contain information about the problem
7690 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7692 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7693 guint32 cols [MONO_TYPEDEF_SIZE];
7698 mono_error_init (error);
7700 if (image_is_dynamic (image)) {
7702 FindUserData user_data;
7704 mono_image_init_name_cache (image);
7705 mono_image_lock (image);
7707 user_data.key = name_space;
7708 user_data.value = NULL;
7709 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7711 if (user_data.value) {
7712 GHashTable *nspace_table = (GHashTable*)user_data.value;
7714 user_data.key = name;
7715 user_data.value = NULL;
7717 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7719 if (user_data.value)
7720 token = GPOINTER_TO_UINT (user_data.value);
7723 mono_image_unlock (image);
7726 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7732 /* add a cache if needed */
7733 for (i = 1; i <= t->rows; ++i) {
7734 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7735 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7737 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7738 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7740 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7742 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7743 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7744 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7745 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7751 return_nested_in (MonoClass *klass, char *nested)
7754 char *s = strchr (nested, '/');
7755 gpointer iter = NULL;
7762 while ((found = mono_class_get_nested_types (klass, &iter))) {
7763 if (strcmp (found->name, nested) == 0) {
7765 return return_nested_in (found, s);
7773 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7775 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7776 MonoImage *file_image;
7780 mono_error_init (error);
7783 * The EXPORTEDTYPES table only contains public types, so have to search the
7785 * Note: image->modules contains the contents of the MODULEREF table, while
7786 * the real module list is in the FILE table.
7788 for (i = 0; i < file_table->rows; i++) {
7789 guint32 cols [MONO_FILE_SIZE];
7790 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7791 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7794 file_image = mono_image_load_file_for_image_checked (image, i + 1, error);
7796 klass = mono_class_from_name_checked (file_image, name_space, name, error);
7797 if (klass || !is_ok (error))
7806 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7808 GHashTable *nspace_table;
7809 MonoImage *loaded_image;
7816 mono_error_init (error);
7818 // Checking visited images avoids stack overflows when cyclic references exist.
7819 if (g_hash_table_lookup (visited_images, image))
7822 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7824 if ((nested = strchr (name, '/'))) {
7825 int pos = nested - name;
7826 int len = strlen (name);
7829 memcpy (buf, name, len + 1);
7831 nested = buf + pos + 1;
7835 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7836 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7837 gboolean res = get_class_from_name (image, name_space, name, &klass);
7840 klass = search_modules (image, name_space, name, error);
7845 return klass ? return_nested_in (klass, nested) : NULL;
7851 mono_image_init_name_cache (image);
7852 mono_image_lock (image);
7854 nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7857 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7859 mono_image_unlock (image);
7861 if (!token && image_is_dynamic (image) && image->modules) {
7862 /* Search modules as well */
7863 for (i = 0; i < image->module_count; ++i) {
7864 MonoImage *module = image->modules [i];
7866 klass = mono_class_from_name_checked (module, name_space, name, error);
7867 if (klass || !is_ok (error))
7873 klass = search_modules (image, name_space, name, error);
7874 if (klass || !is_ok (error))
7879 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7880 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7881 guint32 cols [MONO_EXP_TYPE_SIZE];
7884 idx = mono_metadata_token_index (token);
7886 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7888 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7889 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7890 loaded_image = mono_assembly_load_module_checked (image->assembly, impl >> MONO_IMPLEMENTATION_BITS, error);
7893 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7895 return klass ? return_nested_in (klass, nested) : NULL;
7897 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7898 guint32 assembly_idx;
7900 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7902 mono_assembly_load_reference (image, assembly_idx - 1);
7903 g_assert (image->references [assembly_idx - 1]);
7904 if (image->references [assembly_idx - 1] == (gpointer)-1)
7906 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
7908 return klass ? return_nested_in (klass, nested) : NULL;
7911 g_assert_not_reached ();
7915 token = MONO_TOKEN_TYPE_DEF | token;
7917 klass = mono_class_get_checked (image, token, error);
7919 return return_nested_in (klass, nested);
7924 * mono_class_from_name_checked:
7925 * @image: The MonoImage where the type is looked up in
7926 * @name_space: the type namespace
7927 * @name: the type short name.
7929 * Obtains a MonoClass with a given namespace and a given name which
7930 * is located in the given MonoImage.
7932 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
7933 * set if the class was not found or it will return NULL and set the error if there was a loading error.
7936 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7939 GHashTable *visited_images;
7941 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7943 klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
7945 g_hash_table_destroy (visited_images);
7951 * mono_class_from_name:
7952 * @image: The MonoImage where the type is looked up in
7953 * @name_space: the type namespace
7954 * @name: the type short name.
7956 * Obtains a MonoClass with a given namespace and a given name which
7957 * is located in the given MonoImage.
7959 * To reference nested classes, use the "/" character as a separator.
7960 * For example use "Foo/Bar" to reference the class Bar that is nested
7961 * inside Foo, like this: "class Foo { class Bar {} }".
7964 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7969 klass = mono_class_from_name_checked (image, name_space, name, &error);
7970 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
7976 * mono_class_load_from_name:
7977 * @image: The MonoImage where the type is looked up in
7978 * @name_space: the type namespace
7979 * @name: the type short name.
7981 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
7982 * This function should be used by the runtime for critical types to which there's no way to recover but crash
7983 * If they are missing. Thing of System.Object or System.String.
7986 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
7991 klass = mono_class_from_name_checked (image, name_space, name, &error);
7993 g_error ("Runtime critical type %s.%s not found", name_space, name);
7994 if (!mono_error_ok (&error))
7995 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8000 * mono_class_try_load_from_name:
8001 * @image: The MonoImage where the type is looked up in
8002 * @name_space: the type namespace
8003 * @name: the type short name.
8005 * This function tries to load a type, returning the class was found or NULL otherwise.
8006 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
8008 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
8009 * a type that we would otherwise assume to be available but was not due some error.
8013 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
8018 klass = mono_class_from_name_checked (image, name_space, name, &error);
8019 if (!mono_error_ok (&error))
8020 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8026 * mono_class_is_subclass_of:
8027 * @klass: class to probe if it is a subclass of another one
8028 * @klassc: the class we suspect is the base class
8029 * @check_interfaces: whether we should perform interface checks
8031 * This method determines whether @klass is a subclass of @klassc.
8033 * If the @check_interfaces flag is set, then if @klassc is an interface
8034 * this method return TRUE if the @klass implements the interface or
8035 * if @klass is an interface, if one of its base classes is @klass.
8037 * If @check_interfaces is false then, then if @klass is not an interface
8038 * then it returns TRUE if the @klass is a subclass of @klassc.
8040 * if @klass is an interface and @klassc is System.Object, then this function
8045 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
8046 gboolean check_interfaces)
8048 /* FIXME test for interfaces with variant generic arguments */
8049 mono_class_init (klass);
8050 mono_class_init (klassc);
8052 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
8053 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
8055 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
8058 for (i = 0; i < klass->interface_count; i ++) {
8059 MonoClass *ic = klass->interfaces [i];
8064 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
8069 * MS.NET thinks interfaces are a subclass of Object, so we think it as
8072 if (klassc == mono_defaults.object_class)
8079 mono_type_is_generic_argument (MonoType *type)
8081 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
8085 mono_class_has_variant_generic_params (MonoClass *klass)
8088 MonoGenericContainer *container;
8090 if (!klass->generic_class)
8093 container = klass->generic_class->container_class->generic_container;
8095 for (i = 0; i < container->type_argc; ++i)
8096 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8103 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8105 if (target == candidate)
8108 if (check_for_reference_conv &&
8109 mono_type_is_generic_argument (&target->byval_arg) &&
8110 mono_type_is_generic_argument (&candidate->byval_arg)) {
8111 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8112 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8114 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8117 if (!mono_class_is_assignable_from (target, candidate))
8123 * @container the generic container from the GTD
8124 * @klass: the class to be assigned to
8125 * @oklass: the source class
8127 * Both @klass and @oklass must be instances of the same generic interface.
8129 * Returns: TRUE if @klass can be assigned to a @klass variable
8132 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8135 MonoType **klass_argv, **oklass_argv;
8136 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8137 MonoGenericContainer *container = klass_gtd->generic_container;
8139 if (klass == oklass)
8142 /*Viable candidates are instances of the same generic interface*/
8143 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8146 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8147 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8149 for (j = 0; j < container->type_argc; ++j) {
8150 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8151 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8153 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8157 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8158 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8160 if (param1_class != param2_class) {
8161 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8162 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8164 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8165 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8175 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8177 MonoGenericParam *gparam, *ogparam;
8178 MonoGenericParamInfo *tinfo, *cinfo;
8179 MonoClass **candidate_class;
8180 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8183 if (target == candidate)
8185 if (target->byval_arg.type != candidate->byval_arg.type)
8188 gparam = target->byval_arg.data.generic_param;
8189 ogparam = candidate->byval_arg.data.generic_param;
8190 tinfo = mono_generic_param_info (gparam);
8191 cinfo = mono_generic_param_info (ogparam);
8193 class_constraint_satisfied = FALSE;
8194 valuetype_constraint_satisfied = FALSE;
8196 /*candidate must have a super set of target's special constraints*/
8197 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8198 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8200 if (cinfo->constraints) {
8201 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8202 MonoClass *cc = *candidate_class;
8204 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8205 class_constraint_satisfied = TRUE;
8206 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8207 valuetype_constraint_satisfied = TRUE;
8210 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8211 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8213 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8215 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8217 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8218 valuetype_constraint_satisfied)) {
8223 /*candidate type constraints must be a superset of target's*/
8224 if (tinfo->constraints) {
8225 MonoClass **target_class;
8226 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8227 MonoClass *tc = *target_class;
8230 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8231 * check it's constraints since it satisfy the constraint by itself.
8233 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8236 if (!cinfo->constraints)
8239 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8240 MonoClass *cc = *candidate_class;
8242 if (mono_class_is_assignable_from (tc, cc))
8246 * This happens when we have the following:
8248 * Bar<K> where K : IFace
8249 * Foo<T, U> where T : U where U : IFace
8251 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8254 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8255 if (mono_gparam_is_assignable_from (target, cc))
8259 if (!*candidate_class)
8264 /*candidate itself must have a constraint that satisfy target*/
8265 if (cinfo->constraints) {
8266 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8267 MonoClass *cc = *candidate_class;
8268 if (mono_class_is_assignable_from (target, cc))
8276 * mono_class_is_assignable_from:
8277 * @klass: the class to be assigned to
8278 * @oklass: the source class
8280 * Returns: TRUE if an instance of object oklass can be assigned to an
8281 * instance of object @klass
8284 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8287 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8289 mono_class_init (klass);
8291 if (!oklass->inited)
8292 mono_class_init (oklass);
8294 if (mono_class_has_failure (klass) || mono_class_has_failure (oklass))
8297 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8298 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8300 return mono_gparam_is_assignable_from (klass, oklass);
8303 if (MONO_CLASS_IS_INTERFACE (klass)) {
8304 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8305 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8306 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8310 for (i = 0; constraints [i]; ++i) {
8311 if (mono_class_is_assignable_from (klass, constraints [i]))
8319 /* interface_offsets might not be set for dynamic classes */
8320 if (oklass->ref_info_handle && !oklass->interface_bitmap) {
8322 * oklass might be a generic type parameter but they have
8323 * interface_offsets set.
8325 gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8326 if (!is_ok (&error)) {
8327 mono_error_cleanup (&error);
8332 if (!oklass->interface_bitmap)
8333 /* Happens with generic instances of not-yet created dynamic types */
8335 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8338 if (mono_class_has_variant_generic_params (klass)) {
8340 mono_class_setup_interfaces (oklass, &error);
8341 if (!mono_error_ok (&error)) {
8342 mono_error_cleanup (&error);
8346 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8347 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8348 MonoClass *iface = oklass->interfaces_packed [i];
8350 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8355 } else if (klass->delegate) {
8356 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8358 }else if (klass->rank) {
8359 MonoClass *eclass, *eoclass;
8361 if (oklass->rank != klass->rank)
8364 /* vectors vs. one dimensional arrays */
8365 if (oklass->byval_arg.type != klass->byval_arg.type)
8368 eclass = klass->cast_class;
8369 eoclass = oklass->cast_class;
8372 * a is b does not imply a[] is b[] when a is a valuetype, and
8373 * b is a reference type.
8376 if (eoclass->valuetype) {
8377 if ((eclass == mono_defaults.enum_class) ||
8378 (eclass == mono_defaults.enum_class->parent) ||
8379 (eclass == mono_defaults.object_class))
8383 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8384 } else if (mono_class_is_nullable (klass)) {
8385 if (mono_class_is_nullable (oklass))
8386 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8388 return mono_class_is_assignable_from (klass->cast_class, oklass);
8389 } else if (klass == mono_defaults.object_class)
8392 return mono_class_has_parent (oklass, klass);
8395 /*Check if @oklass is variant compatible with @klass.*/
8397 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8400 MonoType **klass_argv, **oklass_argv;
8401 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8402 MonoGenericContainer *container = klass_gtd->generic_container;
8404 /*Viable candidates are instances of the same generic interface*/
8405 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8408 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8409 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8411 for (j = 0; j < container->type_argc; ++j) {
8412 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8413 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8415 if (param1_class->valuetype != param2_class->valuetype)
8419 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8420 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8422 if (param1_class != param2_class) {
8423 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8424 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8426 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8427 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8435 /*Check if @candidate implements the interface @target*/
8437 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8441 gboolean is_variant = mono_class_has_variant_generic_params (target);
8443 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8444 if (mono_class_is_variant_compatible_slow (target, candidate))
8449 if (candidate == target)
8452 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8453 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8454 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (candidate);
8456 if (tb && tb->interfaces) {
8457 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8458 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8459 MonoClass *iface_class;
8461 /* we can't realize the type here since it can do pretty much anything. */
8464 iface_class = mono_class_from_mono_type (iface->type);
8465 if (iface_class == target)
8467 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8469 if (mono_class_implement_interface_slow (target, iface_class))
8474 /*setup_interfaces don't mono_class_init anything*/
8475 /*FIXME this doesn't handle primitive type arrays.
8476 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8477 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8479 mono_class_setup_interfaces (candidate, &error);
8480 if (!mono_error_ok (&error)) {
8481 mono_error_cleanup (&error);
8485 for (i = 0; i < candidate->interface_count; ++i) {
8486 if (candidate->interfaces [i] == target)
8489 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8492 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8496 candidate = candidate->parent;
8497 } while (candidate);
8503 * Check if @oklass can be assigned to @klass.
8504 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8507 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8509 if (candidate == target)
8511 if (target == mono_defaults.object_class)
8514 if (mono_class_has_parent (candidate, target))
8517 /*If target is not an interface there is no need to check them.*/
8518 if (MONO_CLASS_IS_INTERFACE (target))
8519 return mono_class_implement_interface_slow (target, candidate);
8521 if (target->delegate && mono_class_has_variant_generic_params (target))
8522 return mono_class_is_variant_compatible (target, candidate, FALSE);
8525 MonoClass *eclass, *eoclass;
8527 if (target->rank != candidate->rank)
8530 /* vectors vs. one dimensional arrays */
8531 if (target->byval_arg.type != candidate->byval_arg.type)
8534 eclass = target->cast_class;
8535 eoclass = candidate->cast_class;
8538 * a is b does not imply a[] is b[] when a is a valuetype, and
8539 * b is a reference type.
8542 if (eoclass->valuetype) {
8543 if ((eclass == mono_defaults.enum_class) ||
8544 (eclass == mono_defaults.enum_class->parent) ||
8545 (eclass == mono_defaults.object_class))
8549 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8551 /*FIXME properly handle nullables */
8552 /*FIXME properly handle (M)VAR */
8557 * mono_class_get_cctor:
8558 * @klass: A MonoClass pointer
8560 * Returns: The static constructor of @klass if it exists, NULL otherwise.
8563 mono_class_get_cctor (MonoClass *klass)
8565 MonoCachedClassInfo cached_info;
8567 if (image_is_dynamic (klass->image)) {
8569 * has_cctor is not set for these classes because mono_class_init () is
8572 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8575 if (!klass->has_cctor)
8578 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8580 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8581 if (!mono_error_ok (&error))
8582 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8586 if (klass->generic_class && !klass->methods)
8587 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8589 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8593 * mono_class_get_finalizer:
8594 * @klass: The MonoClass pointer
8596 * Returns: The finalizer method of @klass if it exists, NULL otherwise.
8599 mono_class_get_finalizer (MonoClass *klass)
8601 MonoCachedClassInfo cached_info;
8604 mono_class_init (klass);
8605 if (!mono_class_has_finalizer (klass))
8608 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8610 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8611 if (!mono_error_ok (&error))
8612 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8615 mono_class_setup_vtable (klass);
8616 return klass->vtable [finalize_slot];
8621 * mono_class_needs_cctor_run:
8622 * @klass: the MonoClass pointer
8623 * @caller: a MonoMethod describing the caller
8625 * Determines whenever the class has a static constructor and whenever it
8626 * needs to be called when executing CALLER.
8629 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8633 method = mono_class_get_cctor (klass);
8635 return (method == caller) ? FALSE : TRUE;
8641 * mono_class_array_element_size:
8644 * Returns: The number of bytes an element of type @klass
8645 * uses when stored into an array.
8648 mono_class_array_element_size (MonoClass *klass)
8650 MonoType *type = &klass->byval_arg;
8653 switch (type->type) {
8656 case MONO_TYPE_BOOLEAN:
8660 case MONO_TYPE_CHAR:
8669 case MONO_TYPE_CLASS:
8670 case MONO_TYPE_STRING:
8671 case MONO_TYPE_OBJECT:
8672 case MONO_TYPE_SZARRAY:
8673 case MONO_TYPE_ARRAY:
8674 return sizeof (gpointer);
8679 case MONO_TYPE_VALUETYPE:
8680 if (type->data.klass->enumtype) {
8681 type = mono_class_enum_basetype (type->data.klass);
8682 klass = klass->element_class;
8685 return mono_class_instance_size (klass) - sizeof (MonoObject);
8686 case MONO_TYPE_GENERICINST:
8687 type = &type->data.generic_class->container_class->byval_arg;
8690 case MONO_TYPE_MVAR: {
8693 return mono_type_size (type, &align);
8695 case MONO_TYPE_VOID:
8699 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8705 * mono_array_element_size:
8706 * @ac: pointer to a #MonoArrayClass
8708 * Returns: The size of single array element.
8711 mono_array_element_size (MonoClass *ac)
8713 g_assert (ac->rank);
8714 return ac->sizes.element_size;
8718 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8719 MonoGenericContext *context)
8722 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8723 g_assert (mono_error_ok (&error));
8728 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8729 MonoGenericContext *context, MonoError *error)
8731 mono_error_init (error);
8733 if (image_is_dynamic (image)) {
8734 MonoClass *tmp_handle_class;
8735 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
8737 mono_error_assert_ok (error);
8738 g_assert (tmp_handle_class);
8740 *handle_class = tmp_handle_class;
8742 if (tmp_handle_class == mono_defaults.typehandle_class)
8743 return &((MonoClass*)obj)->byval_arg;
8748 switch (token & 0xff000000) {
8749 case MONO_TOKEN_TYPE_DEF:
8750 case MONO_TOKEN_TYPE_REF:
8751 case MONO_TOKEN_TYPE_SPEC: {
8754 *handle_class = mono_defaults.typehandle_class;
8755 type = mono_type_get_checked (image, token, context, error);
8759 mono_class_init (mono_class_from_mono_type (type));
8760 /* We return a MonoType* as handle */
8763 case MONO_TOKEN_FIELD_DEF: {
8765 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8767 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8771 *handle_class = mono_defaults.fieldhandle_class;
8772 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8776 mono_class_init (klass);
8777 return mono_class_get_field (klass, token);
8779 case MONO_TOKEN_METHOD_DEF:
8780 case MONO_TOKEN_METHOD_SPEC: {
8782 meth = mono_get_method_checked (image, token, NULL, context, error);
8784 *handle_class = mono_defaults.methodhandle_class;
8790 case MONO_TOKEN_MEMBER_REF: {
8791 guint32 cols [MONO_MEMBERREF_SIZE];
8793 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8794 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8795 mono_metadata_decode_blob_size (sig, &sig);
8796 if (*sig == 0x6) { /* it's a field */
8798 MonoClassField *field;
8799 field = mono_field_from_token_checked (image, token, &klass, context, error);
8801 *handle_class = mono_defaults.fieldhandle_class;
8805 meth = mono_get_method_checked (image, token, NULL, context, error);
8807 *handle_class = mono_defaults.methodhandle_class;
8812 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8818 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
8820 MonoClass *handle_class;
8821 mono_error_init (error);
8822 return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
8826 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
8828 return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
8831 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8834 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8836 get_cached_class_info = func;
8840 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8842 if (!get_cached_class_info)
8845 return get_cached_class_info (klass, res);
8849 mono_install_get_class_from_name (MonoGetClassFromName func)
8851 get_class_from_name = func;
8855 * mono_class_get_image:
8857 * Use this method to get the `MonoImage*` where this class came from.
8859 * Returns: The image where this class is defined.
8862 mono_class_get_image (MonoClass *klass)
8864 return klass->image;
8868 * mono_class_get_element_class:
8869 * @klass: the MonoClass to act on
8871 * Use this function to get the element class of an array.
8873 * Returns: The element class of an array.
8876 mono_class_get_element_class (MonoClass *klass)
8878 return klass->element_class;
8882 * mono_class_is_valuetype:
8883 * @klass: the MonoClass to act on
8885 * Use this method to determine if the provided `MonoClass*` represents a value type,
8886 * or a reference type.
8888 * Returns: TRUE if the MonoClass represents a ValueType, FALSE if it represents a reference type.
8891 mono_class_is_valuetype (MonoClass *klass)
8893 return klass->valuetype;
8897 * mono_class_is_enum:
8898 * @klass: the MonoClass to act on
8900 * Use this function to determine if the provided `MonoClass*` represents an enumeration.
8902 * Returns: TRUE if the MonoClass represents an enumeration.
8905 mono_class_is_enum (MonoClass *klass)
8907 return klass->enumtype;
8911 * mono_class_enum_basetype:
8912 * @klass: the MonoClass to act on
8914 * Use this function to get the underlying type for an enumeration value.
8916 * Returns: The underlying type representation for an enumeration.
8919 mono_class_enum_basetype (MonoClass *klass)
8921 if (klass->element_class == klass)
8922 /* SRE or broken types */
8925 return &klass->element_class->byval_arg;
8929 * mono_class_get_parent
8930 * @klass: the MonoClass to act on
8932 * Returns: The parent class for this class.
8935 mono_class_get_parent (MonoClass *klass)
8937 return klass->parent;
8941 * mono_class_get_nesting_type:
8942 * @klass: the MonoClass to act on
8944 * Use this function to obtain the class that the provided `MonoClass*` is nested on.
8946 * If the return is NULL, this indicates that this class is not nested.
8948 * Returns: The container type where this type is nested or NULL if this type is not a nested type.
8951 mono_class_get_nesting_type (MonoClass *klass)
8953 return klass->nested_in;
8957 * mono_class_get_rank:
8958 * @klass: the MonoClass to act on
8960 * Returns: The rank for the array (the number of dimensions).
8963 mono_class_get_rank (MonoClass *klass)
8969 * mono_class_get_flags:
8970 * @klass: the MonoClass to act on
8972 * The type flags from the TypeDef table from the metadata.
8973 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8976 * Returns: The flags from the TypeDef table.
8979 mono_class_get_flags (MonoClass *klass)
8981 return klass->flags;
8985 * mono_class_get_name
8986 * @klass: the MonoClass to act on
8988 * Returns: The name of the class.
8991 mono_class_get_name (MonoClass *klass)
8997 * mono_class_get_namespace:
8998 * @klass: the MonoClass to act on
9000 * Returns: The namespace of the class.
9003 mono_class_get_namespace (MonoClass *klass)
9005 return klass->name_space;
9009 * mono_class_get_type:
9010 * @klass: the MonoClass to act on
9012 * This method returns the internal Type representation for the class.
9014 * Returns: The MonoType from the class.
9017 mono_class_get_type (MonoClass *klass)
9019 return &klass->byval_arg;
9023 * mono_class_get_type_token:
9024 * @klass: the MonoClass to act on
9026 * This method returns type token for the class.
9028 * Returns: The type token for the class.
9031 mono_class_get_type_token (MonoClass *klass)
9033 return klass->type_token;
9037 * mono_class_get_byref_type:
9038 * @klass: the MonoClass to act on
9043 mono_class_get_byref_type (MonoClass *klass)
9045 return &klass->this_arg;
9049 * mono_class_num_fields:
9050 * @klass: the MonoClass to act on
9052 * Returns: The number of static and instance fields in the class.
9055 mono_class_num_fields (MonoClass *klass)
9057 return klass->field.count;
9061 * mono_class_num_methods:
9062 * @klass: the MonoClass to act on
9064 * Returns: The number of methods in the class.
9067 mono_class_num_methods (MonoClass *klass)
9069 return klass->method.count;
9073 * mono_class_num_properties
9074 * @klass: the MonoClass to act on
9076 * Returns: The number of properties in the class.
9079 mono_class_num_properties (MonoClass *klass)
9081 mono_class_setup_properties (klass);
9083 return klass->ext->property.count;
9087 * mono_class_num_events:
9088 * @klass: the MonoClass to act on
9090 * Returns: The number of events in the class.
9093 mono_class_num_events (MonoClass *klass)
9095 mono_class_setup_events (klass);
9097 return klass->ext->event.count;
9101 * mono_class_get_fields:
9102 * @klass: the MonoClass to act on
9104 * This routine is an iterator routine for retrieving the fields in a class.
9106 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9107 * iterate over all of the elements. When no more values are
9108 * available, the return value is NULL.
9110 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
9113 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9115 MonoClassField* field;
9119 mono_class_setup_fields_locking (klass);
9120 if (mono_class_has_failure (klass))
9122 /* start from the first */
9123 if (klass->field.count) {
9124 *iter = &klass->fields [0];
9125 return &klass->fields [0];
9131 field = (MonoClassField *)*iter;
9133 if (field < &klass->fields [klass->field.count]) {
9141 * mono_class_get_methods
9142 * @klass: the MonoClass to act on
9144 * This routine is an iterator routine for retrieving the fields in a class.
9146 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9147 * iterate over all of the elements. When no more values are
9148 * available, the return value is NULL.
9150 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
9153 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9155 MonoMethod** method;
9159 mono_class_setup_methods (klass);
9162 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9163 * FIXME we should better report this error to the caller
9165 if (!klass->methods)
9167 /* start from the first */
9168 if (klass->method.count) {
9169 *iter = &klass->methods [0];
9170 return klass->methods [0];
9176 method = (MonoMethod **)*iter;
9178 if (method < &klass->methods [klass->method.count]) {
9186 * mono_class_get_virtual_methods:
9188 * Iterate over the virtual methods of KLASS.
9190 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9193 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9195 MonoMethod** method;
9198 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9200 mono_class_setup_methods (klass);
9202 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9203 * FIXME we should better report this error to the caller
9205 if (!klass->methods)
9207 /* start from the first */
9208 method = &klass->methods [0];
9210 method = (MonoMethod **)*iter;
9213 while (method < &klass->methods [klass->method.count]) {
9214 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9218 if (method < &klass->methods [klass->method.count]) {
9225 /* Search directly in metadata to avoid calling setup_methods () */
9226 MonoMethod *res = NULL;
9232 start_index = GPOINTER_TO_UINT (*iter);
9235 for (i = start_index; i < klass->method.count; ++i) {
9238 /* klass->method.first points into the methodptr table */
9239 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
9241 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9245 if (i < klass->method.count) {
9247 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9248 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9250 /* Add 1 here so the if (*iter) check fails */
9251 *iter = GUINT_TO_POINTER (i + 1);
9260 * mono_class_get_properties:
9261 * @klass: the MonoClass to act on
9263 * This routine is an iterator routine for retrieving the properties in a class.
9265 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9266 * iterate over all of the elements. When no more values are
9267 * available, the return value is NULL.
9269 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9272 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9274 MonoProperty* property;
9278 mono_class_setup_properties (klass);
9279 /* start from the first */
9280 if (klass->ext->property.count) {
9281 *iter = &klass->ext->properties [0];
9282 return (MonoProperty *)*iter;
9288 property = (MonoProperty *)*iter;
9290 if (property < &klass->ext->properties [klass->ext->property.count]) {
9292 return (MonoProperty *)*iter;
9298 * mono_class_get_events:
9299 * @klass: the MonoClass to act on
9301 * This routine is an iterator routine for retrieving the properties in a class.
9303 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9304 * iterate over all of the elements. When no more values are
9305 * available, the return value is NULL.
9307 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9310 mono_class_get_events (MonoClass* klass, gpointer *iter)
9316 mono_class_setup_events (klass);
9317 /* start from the first */
9318 if (klass->ext->event.count) {
9319 *iter = &klass->ext->events [0];
9320 return (MonoEvent *)*iter;
9326 event = (MonoEvent *)*iter;
9328 if (event < &klass->ext->events [klass->ext->event.count]) {
9330 return (MonoEvent *)*iter;
9336 * mono_class_get_interfaces
9337 * @klass: the MonoClass to act on
9339 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9341 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9342 * iterate over all of the elements. When no more values are
9343 * available, the return value is NULL.
9345 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9348 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9356 mono_class_init (klass);
9357 if (!klass->interfaces_inited) {
9358 mono_class_setup_interfaces (klass, &error);
9359 if (!mono_error_ok (&error)) {
9360 mono_error_cleanup (&error);
9364 /* start from the first */
9365 if (klass->interface_count) {
9366 *iter = &klass->interfaces [0];
9367 return klass->interfaces [0];
9373 iface = (MonoClass **)*iter;
9375 if (iface < &klass->interfaces [klass->interface_count]) {
9383 setup_nested_types (MonoClass *klass)
9386 GList *classes, *nested_classes, *l;
9389 if (klass->nested_classes_inited)
9392 if (!klass->type_token)
9393 klass->nested_classes_inited = TRUE;
9395 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9399 guint32 cols [MONO_NESTED_CLASS_SIZE];
9400 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9401 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9402 if (!mono_error_ok (&error)) {
9403 /*FIXME don't swallow the error message*/
9404 mono_error_cleanup (&error);
9406 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9410 classes = g_list_prepend (classes, nclass);
9412 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9415 mono_class_alloc_ext (klass);
9417 nested_classes = NULL;
9418 for (l = classes; l; l = l->next)
9419 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9420 g_list_free (classes);
9422 mono_image_lock (klass->image);
9424 mono_memory_barrier ();
9425 if (!klass->nested_classes_inited) {
9426 klass->ext->nested_classes = nested_classes;
9427 mono_memory_barrier ();
9428 klass->nested_classes_inited = TRUE;
9431 mono_image_unlock (klass->image);
9435 * mono_class_get_nested_types
9436 * @klass: the MonoClass to act on
9438 * This routine is an iterator routine for retrieving the nested types of a class.
9439 * This works only if @klass is non-generic, or a generic type definition.
9441 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9442 * iterate over all of the elements. When no more values are
9443 * available, the return value is NULL.
9445 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9448 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9454 if (!klass->nested_classes_inited)
9455 setup_nested_types (klass);
9458 /* start from the first */
9459 if (klass->ext && klass->ext->nested_classes) {
9460 *iter = klass->ext->nested_classes;
9461 return (MonoClass *)klass->ext->nested_classes->data;
9463 /* no nested types */
9467 item = (GList *)*iter;
9471 return (MonoClass *)item->data;
9478 * mono_class_is_delegate
9479 * @klass: the MonoClass to act on
9481 * Returns: TRUE if the MonoClass represents a System.Delegate.
9484 mono_class_is_delegate (MonoClass *klass)
9486 return klass->delegate;
9490 * mono_class_implements_interface
9491 * @klass: The MonoClass to act on
9492 * @interface: The interface to check if @klass implements.
9494 * Returns: TRUE if @klass implements @interface.
9497 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9499 return mono_class_is_assignable_from (iface, klass);
9503 * mono_field_get_name:
9504 * @field: the MonoClassField to act on
9506 * Returns: The name of the field.
9509 mono_field_get_name (MonoClassField *field)
9515 * mono_field_get_type:
9516 * @field: the MonoClassField to act on
9518 * Returns: MonoType of the field.
9521 mono_field_get_type (MonoClassField *field)
9524 MonoType *type = mono_field_get_type_checked (field, &error);
9525 if (!mono_error_ok (&error)) {
9526 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9527 mono_error_cleanup (&error);
9534 * mono_field_get_type_checked:
9535 * @field: the MonoClassField to act on
9536 * @error: used to return any erro found while retrieving @field type
9538 * Returns: MonoType of the field.
9541 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9543 mono_error_init (error);
9545 mono_field_resolve_type (field, error);
9550 * mono_field_get_parent:
9551 * @field: the MonoClassField to act on
9553 * Returns: MonoClass where the field was defined.
9556 mono_field_get_parent (MonoClassField *field)
9558 return field->parent;
9562 * mono_field_get_flags;
9563 * @field: the MonoClassField to act on
9565 * The metadata flags for a field are encoded using the
9566 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9568 * Returns: The flags for the field.
9571 mono_field_get_flags (MonoClassField *field)
9574 return mono_field_resolve_flags (field);
9575 return field->type->attrs;
9579 * mono_field_get_offset:
9580 * @field: the MonoClassField to act on
9582 * Returns: The field offset.
9585 mono_field_get_offset (MonoClassField *field)
9587 return field->offset;
9591 mono_field_get_rva (MonoClassField *field)
9595 MonoClass *klass = field->parent;
9596 MonoFieldDefaultValue *field_def_values;
9598 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9600 if (!klass->ext || !klass->ext->field_def_values) {
9601 mono_class_alloc_ext (klass);
9603 field_def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9605 mono_image_lock (klass->image);
9606 if (!klass->ext->field_def_values)
9607 klass->ext->field_def_values = field_def_values;
9608 mono_image_unlock (klass->image);
9611 field_index = mono_field_get_index (field);
9613 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9614 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9616 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9617 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9620 return klass->ext->field_def_values [field_index].data;
9624 * mono_field_get_data:
9625 * @field: the MonoClassField to act on
9627 * Returns: A pointer to the metadata constant value or to the field
9628 * data if it has an RVA flag.
9631 mono_field_get_data (MonoClassField *field)
9633 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9634 MonoTypeEnum def_type;
9636 return mono_class_get_field_default_value (field, &def_type);
9637 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9638 return mono_field_get_rva (field);
9645 * mono_property_get_name:
9646 * @prop: the MonoProperty to act on
9648 * Returns: The name of the property
9651 mono_property_get_name (MonoProperty *prop)
9657 * mono_property_get_set_method
9658 * @prop: the MonoProperty to act on.
9660 * Returns: The setter method of the property (A MonoMethod)
9663 mono_property_get_set_method (MonoProperty *prop)
9669 * mono_property_get_get_method
9670 * @prop: the MonoProperty to act on.
9672 * Returns: The setter method of the property (A MonoMethod)
9675 mono_property_get_get_method (MonoProperty *prop)
9681 * mono_property_get_parent:
9682 * @prop: the MonoProperty to act on.
9684 * Returns: The MonoClass where the property was defined.
9687 mono_property_get_parent (MonoProperty *prop)
9689 return prop->parent;
9693 * mono_property_get_flags:
9694 * @prop: the MonoProperty to act on.
9696 * The metadata flags for a property are encoded using the
9697 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9699 * Returns: The flags for the property.
9702 mono_property_get_flags (MonoProperty *prop)
9708 * mono_event_get_name:
9709 * @event: the MonoEvent to act on
9711 * Returns: The name of the event.
9714 mono_event_get_name (MonoEvent *event)
9720 * mono_event_get_add_method:
9721 * @event: The MonoEvent to act on.
9723 * Returns: The @add' method for the event (a MonoMethod).
9726 mono_event_get_add_method (MonoEvent *event)
9732 * mono_event_get_remove_method:
9733 * @event: The MonoEvent to act on.
9735 * Returns: The @remove method for the event (a MonoMethod).
9738 mono_event_get_remove_method (MonoEvent *event)
9740 return event->remove;
9744 * mono_event_get_raise_method:
9745 * @event: The MonoEvent to act on.
9747 * Returns: The @raise method for the event (a MonoMethod).
9750 mono_event_get_raise_method (MonoEvent *event)
9752 return event->raise;
9756 * mono_event_get_parent:
9757 * @event: the MonoEvent to act on.
9759 * Returns: The MonoClass where the event is defined.
9762 mono_event_get_parent (MonoEvent *event)
9764 return event->parent;
9768 * mono_event_get_flags
9769 * @event: the MonoEvent to act on.
9771 * The metadata flags for an event are encoded using the
9772 * EVENT_* constants. See the tabledefs.h file for details.
9774 * Returns: The flags for the event.
9777 mono_event_get_flags (MonoEvent *event)
9779 return event->attrs;
9783 * mono_class_get_method_from_name:
9784 * @klass: where to look for the method
9785 * @name: name of the method
9786 * @param_count: number of parameters. -1 for any number.
9788 * Obtains a MonoMethod with a given name and number of parameters.
9789 * It only works if there are no multiple signatures for any given method name.
9792 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9794 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9798 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9800 MonoMethod *res = NULL;
9803 /* Search directly in the metadata to avoid calling setup_methods () */
9804 for (i = 0; i < klass->method.count; ++i) {
9806 guint32 cols [MONO_METHOD_SIZE];
9808 MonoMethodSignature *sig;
9810 /* klass->method.first points into the methodptr table */
9811 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9813 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9814 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9816 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9819 if (param_count == -1) {
9823 sig = mono_method_signature_checked (method, &error);
9825 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9828 if (sig->param_count == param_count) {
9839 * mono_class_get_method_from_name_flags:
9840 * @klass: where to look for the method
9841 * @name_space: name of the method
9842 * @param_count: number of parameters. -1 for any number.
9843 * @flags: flags which must be set in the method
9845 * Obtains a MonoMethod with a given name and number of parameters.
9846 * It only works if there are no multiple signatures for any given method name.
9849 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9851 MonoMethod *res = NULL;
9854 mono_class_init (klass);
9856 if (klass->generic_class && !klass->methods) {
9857 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9860 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9861 if (!mono_error_ok (&error))
9862 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9867 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9868 mono_class_setup_methods (klass);
9870 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9871 See mono/tests/array_load_exception.il
9872 FIXME we should better report this error to the caller
9874 if (!klass->methods)
9876 for (i = 0; i < klass->method.count; ++i) {
9877 MonoMethod *method = klass->methods [i];
9879 if (method->name[0] == name [0] &&
9880 !strcmp (name, method->name) &&
9881 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9882 ((method->flags & flags) == flags)) {
9889 res = find_method_in_metadata (klass, name, param_count, flags);
9896 * mono_class_set_failure:
9897 * @klass: class in which the failure was detected
9898 * @ex_type: the kind of exception/error to be thrown (later)
9899 * @ex_data: exception data (specific to each type of exception/error)
9901 * Keep a detected failure informations in the class for later processing.
9902 * Note that only the first failure is kept.
9904 * LOCKING: Acquires the loader lock.
9907 mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error)
9909 g_assert (boxed_error != NULL);
9911 if (mono_class_has_failure (klass))
9914 mono_loader_lock ();
9915 klass->has_failure = 1;
9916 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, boxed_error);
9917 mono_loader_unlock ();
9923 mono_class_has_failure (const MonoClass *klass)
9925 g_assert (klass != NULL);
9926 return klass->has_failure != 0;
9931 * mono_class_set_type_load_failure:
9932 * @klass: class in which the failure was detected
9933 * @fmt: Printf-style error message string.
9935 * Collect detected failure informaion in the class for later processing.
9936 * The error is stored as a MonoErrorBoxed as with mono_error_set_type_load_class ()
9937 * Note that only the first failure is kept.
9939 * Returns FALSE if a failure was already set on the class, or TRUE otherwise.
9941 * LOCKING: Acquires the loader lock.
9944 mono_class_set_type_load_failure (MonoClass *klass, const char * fmt, ...)
9946 MonoError prepare_error;
9949 if (mono_class_has_failure (klass))
9952 mono_error_init (&prepare_error);
9954 va_start (args, fmt);
9955 mono_error_vset_type_load_class (&prepare_error, klass, fmt, args);
9958 MonoErrorBoxed *box = mono_error_box (&prepare_error, klass->image);
9959 mono_error_cleanup (&prepare_error);
9960 return mono_class_set_failure (klass, box);
9964 * mono_class_get_exception_data:
9966 * Return the exception_data property of KLASS.
9968 * LOCKING: Acquires the loader lock.
9971 mono_class_get_exception_data (const MonoClass *klass)
9973 return mono_image_property_lookup (klass->image, (MonoClass*)klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9977 * mono_classes_init:
9979 * Initialize the resources used by this module.
9982 mono_classes_init (void)
9984 mono_os_mutex_init (&classes_mutex);
9986 mono_counters_register ("Inflated methods size",
9987 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9988 mono_counters_register ("Inflated classes",
9989 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9990 mono_counters_register ("Inflated classes size",
9991 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9992 mono_counters_register ("MonoClass size",
9993 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9994 mono_counters_register ("MonoClassExt size",
9995 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
9999 * mono_classes_cleanup:
10001 * Free the resources used by this module.
10004 mono_classes_cleanup (void)
10006 if (global_interface_bitset)
10007 mono_bitset_free (global_interface_bitset);
10008 global_interface_bitset = NULL;
10009 mono_os_mutex_destroy (&classes_mutex);
10013 * mono_class_get_exception_for_failure:
10014 * @klass: class in which the failure was detected
10016 * Return a constructed MonoException than the caller can then throw
10017 * using mono_raise_exception - or NULL if no failure is present (or
10018 * doesn't result in an exception).
10021 mono_class_get_exception_for_failure (MonoClass *klass)
10023 if (!mono_class_has_failure (klass))
10025 MonoError unboxed_error;
10026 mono_error_init (&unboxed_error);
10027 mono_error_set_for_class_failure (&unboxed_error, klass);
10028 return mono_error_convert_to_exception (&unboxed_error);
10032 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
10034 outer_klass = mono_class_get_generic_type_definition (outer_klass);
10035 inner_klass = mono_class_get_generic_type_definition (inner_klass);
10037 if (outer_klass == inner_klass)
10039 inner_klass = inner_klass->nested_in;
10040 } while (inner_klass);
10045 mono_class_get_generic_type_definition (MonoClass *klass)
10047 return klass->generic_class ? klass->generic_class->container_class : klass;
10051 * Check if @klass is a subtype of @parent ignoring generic instantiations.
10053 * Generic instantiations are ignored for all super types of @klass.
10055 * Visibility checks ignoring generic instantiations.
10058 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
10061 klass = mono_class_get_generic_type_definition (klass);
10062 parent = mono_class_get_generic_type_definition (parent);
10063 mono_class_setup_supertypes (klass);
10065 for (i = 0; i < klass->idepth; ++i) {
10066 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
10072 * Subtype can only access parent members with family protection if the site object
10073 * is subclass of Subtype. For example:
10074 * class A { protected int x; }
10076 * void valid_access () {
10080 * void invalid_access () {
10087 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
10089 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
10092 if (context_klass == NULL)
10094 /*if access_klass is not member_klass context_klass must be type compat*/
10095 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10101 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10104 if (accessing == accessed)
10106 if (!accessed || !accessing)
10109 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10110 * anywhere so untrusted friends are not safe to access platform's code internals */
10111 if (mono_security_core_clr_enabled ()) {
10112 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10116 mono_assembly_load_friends (accessed);
10117 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10118 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10119 /* Be conservative with checks */
10120 if (!friend_->name)
10122 if (strcmp (accessing->aname.name, friend_->name))
10124 if (friend_->public_key_token [0]) {
10125 if (!accessing->aname.public_key_token [0])
10127 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10136 * If klass is a generic type or if it is derived from a generic type, return the
10137 * MonoClass of the generic definition
10138 * Returns NULL if not found
10141 get_generic_definition_class (MonoClass *klass)
10144 if (klass->generic_class && klass->generic_class->container_class)
10145 return klass->generic_class->container_class;
10146 klass = klass->parent;
10152 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10155 for (i = 0; i < ginst->type_argc; ++i) {
10156 MonoType *type = ginst->type_argv[i];
10157 switch (type->type) {
10158 case MONO_TYPE_SZARRAY:
10159 if (!can_access_type (access_klass, type->data.klass))
10162 case MONO_TYPE_ARRAY:
10163 if (!can_access_type (access_klass, type->data.array->eklass))
10166 case MONO_TYPE_PTR:
10167 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10170 case MONO_TYPE_CLASS:
10171 case MONO_TYPE_VALUETYPE:
10172 case MONO_TYPE_GENERICINST:
10173 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10183 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10187 if (access_klass == member_klass)
10190 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10193 if (access_klass->element_class && !access_klass->enumtype)
10194 access_klass = access_klass->element_class;
10196 if (member_klass->element_class && !member_klass->enumtype)
10197 member_klass = member_klass->element_class;
10199 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10201 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10204 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
10207 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10210 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10213 /*Non nested type with nested visibility. We just fail it.*/
10214 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10217 switch (access_level) {
10218 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10219 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10221 case TYPE_ATTRIBUTE_PUBLIC:
10224 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10227 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10228 return is_nesting_type (member_klass, access_klass);
10230 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10231 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10233 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10234 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10236 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10237 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10238 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10240 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10241 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10242 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10247 /* FIXME: check visibility of type, too */
10249 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10251 MonoClass *member_generic_def;
10252 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10255 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
10256 access_klass->generic_container) &&
10257 (member_generic_def = get_generic_definition_class (member_klass))) {
10258 MonoClass *access_container;
10260 if (access_klass->generic_container)
10261 access_container = access_klass;
10263 access_container = access_klass->generic_class->container_class;
10265 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10269 /* Partition I 8.5.3.2 */
10270 /* the access level values are the same for fields and methods */
10271 switch (access_level) {
10272 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10273 /* same compilation unit */
10274 return access_klass->image == member_klass->image;
10275 case FIELD_ATTRIBUTE_PRIVATE:
10276 return access_klass == member_klass;
10277 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10278 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10279 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10282 case FIELD_ATTRIBUTE_ASSEMBLY:
10283 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10284 case FIELD_ATTRIBUTE_FAMILY:
10285 if (is_valid_family_access (access_klass, member_klass, context_klass))
10288 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10289 if (is_valid_family_access (access_klass, member_klass, context_klass))
10291 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10292 case FIELD_ATTRIBUTE_PUBLIC:
10299 * mono_method_can_access_field:
10300 * @method: Method that will attempt to access the field
10301 * @field: the field to access
10303 * Used to determine if a method is allowed to access the specified field.
10305 * Returns: TRUE if the given @method is allowed to access the @field while following
10306 * the accessibility rules of the CLI.
10309 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10311 /* FIXME: check all overlapping fields */
10312 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10314 MonoClass *nested = method->klass->nested_in;
10316 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10319 nested = nested->nested_in;
10326 * mono_method_can_access_method:
10327 * @method: Method that will attempt to access the other method
10328 * @called: the method that we want to probe for accessibility.
10330 * Used to determine if the @method is allowed to access the specified @called method.
10332 * Returns: TRUE if the given @method is allowed to invoke the @called while following
10333 * the accessibility rules of the CLI.
10336 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10338 method = mono_method_get_method_definition (method);
10339 called = mono_method_get_method_definition (called);
10340 return mono_method_can_access_method_full (method, called, NULL);
10344 * mono_method_can_access_method_full:
10345 * @method: The caller method
10346 * @called: The called method
10347 * @context_klass: The static type on stack of the owner @called object used
10349 * This function must be used with instance calls, as they have more strict family accessibility.
10350 * It can be used with static methods, but context_klass should be NULL.
10352 * Returns: TRUE if caller have proper visibility and acessibility to @called
10355 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10357 /* Wrappers are except from access checks */
10358 if (method->wrapper_type != MONO_WRAPPER_NONE || called->wrapper_type != MONO_WRAPPER_NONE)
10361 MonoClass *access_class = method->klass;
10362 MonoClass *member_class = called->klass;
10363 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10365 MonoClass *nested = access_class->nested_in;
10367 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10370 nested = nested->nested_in;
10377 can = can_access_type (access_class, member_class);
10379 MonoClass *nested = access_class->nested_in;
10381 can = can_access_type (nested, member_class);
10384 nested = nested->nested_in;
10391 if (called->is_inflated) {
10392 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10393 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10402 * mono_method_can_access_field_full:
10403 * @method: The caller method
10404 * @field: The accessed field
10405 * @context_klass: The static type on stack of the owner @field object used
10407 * This function must be used with instance fields, as they have more strict family accessibility.
10408 * It can be used with static fields, but context_klass should be NULL.
10410 * Returns: TRUE if caller have proper visibility and acessibility to @field
10413 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10415 MonoClass *access_class = method->klass;
10416 MonoClass *member_class = field->parent;
10417 /* FIXME: check all overlapping fields */
10418 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10420 MonoClass *nested = access_class->nested_in;
10422 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10425 nested = nested->nested_in;
10432 can = can_access_type (access_class, member_class);
10434 MonoClass *nested = access_class->nested_in;
10436 can = can_access_type (nested, member_class);
10439 nested = nested->nested_in;
10449 * mono_class_can_access_class:
10450 * @source_class: The source class
10451 * @target_class: The accessed class
10453 * This function returns is @target_class is visible to @source_class
10455 * Returns: TRUE if source have proper visibility and acessibility to target
10458 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10460 return can_access_type (source_class, target_class);
10464 * mono_type_is_valid_enum_basetype:
10465 * @type: The MonoType to check
10467 * Returns: TRUE if the type can be used as the basetype of an enum
10469 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10470 switch (type->type) {
10473 case MONO_TYPE_BOOLEAN:
10476 case MONO_TYPE_CHAR:
10490 * mono_class_is_valid_enum:
10491 * @klass: An enum class to be validated
10493 * This method verify the required properties an enum should have.
10495 * Returns: TRUE if the informed enum class is valid
10497 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10498 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10499 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10501 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10502 MonoClassField * field;
10503 gpointer iter = NULL;
10504 gboolean found_base_field = FALSE;
10506 g_assert (klass->enumtype);
10507 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10508 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10512 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10515 while ((field = mono_class_get_fields (klass, &iter))) {
10516 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10517 if (found_base_field)
10519 found_base_field = TRUE;
10520 if (!mono_type_is_valid_enum_basetype (field->type))
10525 if (!found_base_field)
10528 if (klass->method.count > 0)
10535 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10537 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10541 * mono_class_setup_interface_id:
10543 * Initializes MonoClass::interface_id if required.
10545 * LOCKING: Acquires the loader lock.
10548 mono_class_setup_interface_id (MonoClass *klass)
10550 mono_loader_lock ();
10551 if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10552 klass->interface_id = mono_get_unique_iid (klass);
10553 mono_loader_unlock ();
10557 * mono_class_alloc_ext:
10559 * Allocate klass->ext if not already done.
10562 mono_class_alloc_ext (MonoClass *klass)
10569 ext = (MonoClassExt *)mono_class_alloc0 (klass, sizeof (MonoClassExt));
10570 mono_image_lock (klass->image);
10571 mono_memory_barrier ();
10574 class_ext_size += sizeof (MonoClassExt);
10575 mono_image_unlock (klass->image);
10579 * mono_class_setup_interfaces:
10581 * Initialize klass->interfaces/interfaces_count.
10582 * LOCKING: Acquires the loader lock.
10583 * This function can fail the type.
10586 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10588 int i, interface_count;
10589 MonoClass **interfaces;
10591 mono_error_init (error);
10593 if (klass->interfaces_inited)
10596 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10597 MonoType *args [1];
10599 /* generic IList, ICollection, IEnumerable */
10600 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10601 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10603 args [0] = &klass->element_class->byval_arg;
10604 interfaces [0] = mono_class_bind_generic_parameters (
10605 mono_defaults.generic_ilist_class, 1, args, FALSE);
10606 if (interface_count > 1)
10607 interfaces [1] = mono_class_bind_generic_parameters (
10608 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10609 } else if (klass->generic_class) {
10610 MonoClass *gklass = klass->generic_class->container_class;
10612 mono_class_setup_interfaces (gklass, error);
10613 if (!mono_error_ok (error)) {
10614 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10618 interface_count = gklass->interface_count;
10619 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10620 for (i = 0; i < interface_count; i++) {
10621 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10622 if (!mono_error_ok (error)) {
10623 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10628 interface_count = 0;
10632 mono_image_lock (klass->image);
10634 if (!klass->interfaces_inited) {
10635 klass->interface_count = interface_count;
10636 klass->interfaces = interfaces;
10638 mono_memory_barrier ();
10640 klass->interfaces_inited = TRUE;
10643 mono_image_unlock (klass->image);
10647 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10649 MonoClass *klass = field->parent;
10650 MonoImage *image = klass->image;
10651 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10652 int field_idx = field - klass->fields;
10654 mono_error_init (error);
10657 MonoClassField *gfield = >d->fields [field_idx];
10658 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10659 if (!mono_error_ok (error)) {
10660 mono_class_set_type_load_failure (klass, "Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10663 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10664 if (!mono_error_ok (error)) {
10665 mono_class_set_type_load_failure (klass, "Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10669 guint32 cols [MONO_FIELD_SIZE];
10670 MonoGenericContainer *container = NULL;
10671 int idx = klass->field.first + field_idx;
10673 /*FIXME, in theory we do not lazy load SRE fields*/
10674 g_assert (!image_is_dynamic (image));
10676 if (klass->generic_container) {
10677 container = klass->generic_container;
10679 container = gtd->generic_container;
10680 g_assert (container);
10683 /* klass->field.first and idx points into the fieldptr table */
10684 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10686 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10687 mono_error_set_type_load_class (error, klass, "Could not verify field %s signature", field->name);;
10688 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
10692 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10694 mono_metadata_decode_value (sig, &sig);
10695 /* FIELD signature == 0x06 */
10696 g_assert (*sig == 0x06);
10698 field->type = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10699 if (!field->type) {
10700 mono_class_set_type_load_failure (klass, "Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10706 mono_field_resolve_flags (MonoClassField *field)
10708 MonoClass *klass = field->parent;
10709 MonoImage *image = klass->image;
10710 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10711 int field_idx = field - klass->fields;
10715 MonoClassField *gfield = >d->fields [field_idx];
10716 return mono_field_get_flags (gfield);
10718 int idx = klass->field.first + field_idx;
10720 /*FIXME, in theory we do not lazy load SRE fields*/
10721 g_assert (!image_is_dynamic (image));
10723 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10728 * mono_class_setup_basic_field_info:
10729 * @class: The class to initialize
10731 * Initializes the klass->fields array of fields.
10732 * Aquires the loader lock.
10735 mono_class_setup_basic_field_info_locking (MonoClass *klass)
10737 mono_loader_lock ();
10738 mono_class_setup_basic_field_info (klass);
10739 mono_loader_unlock ();
10743 * mono_class_get_fields_lazy:
10744 * @klass: the MonoClass to act on
10746 * This routine is an iterator routine for retrieving the fields in a class.
10747 * Only minimal information about fields are loaded. Accessors must be used
10748 * for all MonoClassField returned.
10750 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10751 * iterate over all of the elements. When no more values are
10752 * available, the return value is NULL.
10754 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10757 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10759 MonoClassField* field;
10763 mono_class_setup_basic_field_info_locking (klass);
10764 if (!klass->fields)
10766 /* start from the first */
10767 if (klass->field.count) {
10768 *iter = &klass->fields [0];
10769 return (MonoClassField *)*iter;
10775 field = (MonoClassField *)*iter;
10777 if (field < &klass->fields [klass->field.count]) {
10779 return (MonoClassField *)*iter;
10785 mono_class_full_name (MonoClass *klass)
10787 return mono_type_full_name (&klass->byval_arg);
10790 /* Declare all shared lazy type lookup functions */
10791 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, System.Runtime.InteropServices, SafeHandle)