2 * class.c: Class management for the Mono runtime
5 * Miguel de Icaza (miguel@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9 * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
10 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
20 #include <mono/metadata/image.h>
21 #include <mono/metadata/image-internals.h>
22 #include <mono/metadata/assembly.h>
23 #include <mono/metadata/assembly-internals.h>
24 #include <mono/metadata/metadata.h>
25 #include <mono/metadata/metadata-internals.h>
26 #include <mono/metadata/profiler-private.h>
27 #include <mono/metadata/tabledefs.h>
28 #include <mono/metadata/tokentype.h>
29 #include <mono/metadata/class-internals.h>
30 #include <mono/metadata/object.h>
31 #include <mono/metadata/appdomain.h>
32 #include <mono/metadata/mono-endian.h>
33 #include <mono/metadata/debug-helpers.h>
34 #include <mono/metadata/reflection.h>
35 #include <mono/metadata/exception.h>
36 #include <mono/metadata/security-manager.h>
37 #include <mono/metadata/security-core-clr.h>
38 #include <mono/metadata/attrdefs.h>
39 #include <mono/metadata/gc-internals.h>
40 #include <mono/metadata/verify-internals.h>
41 #include <mono/metadata/mono-debug.h>
42 #include <mono/utils/mono-counters.h>
43 #include <mono/utils/mono-string.h>
44 #include <mono/utils/mono-error-internals.h>
45 #include <mono/utils/mono-logger-internals.h>
46 #include <mono/utils/mono-memory-model.h>
47 #include <mono/utils/atomic.h>
48 #include <mono/utils/bsearch.h>
49 #include <mono/utils/checked-build.h>
53 gboolean mono_print_vtable = FALSE;
54 gboolean mono_align_small_structs = FALSE;
57 guint32 inflated_classes_size, inflated_methods_size;
58 guint32 classes_size, class_ext_size, class_ext_count;
59 guint32 class_def_count, class_gtd_count, class_ginst_count, class_gparam_count, class_array_count, class_pointer_count;
61 /* Low level lock which protects data structures in this module */
62 static mono_mutex_t classes_mutex;
64 /* Function supplied by the runtime to find classes by name using information from the AOT file */
65 static MonoGetClassFromName get_class_from_name = NULL;
67 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error);
68 static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
69 static gboolean can_access_type (MonoClass *access_klass, MonoClass *member_klass);
70 static MonoMethod* find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags);
71 static int generic_array_methods (MonoClass *klass);
72 static void setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos);
74 static MonoMethod* mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter);
75 static char* mono_assembly_name_from_token (MonoImage *image, guint32 type_token);
76 static void mono_field_resolve_type (MonoClassField *field, MonoError *error);
77 static guint32 mono_field_resolve_flags (MonoClassField *field);
78 static void mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup);
79 static void mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gklass);
81 static gboolean mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error);
82 static gpointer mono_class_get_exception_data (const MonoClass *klass);
86 We use gclass recording to allow recursive system f types to be referenced by a parent.
88 Given the following type hierarchy:
90 class TextBox : TextBoxBase<TextBox> {}
91 class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
92 class TextInput<T> : Input<T> where T: TextInput<T> {}
95 The runtime tries to load TextBoxBase<>.
96 To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
97 To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
98 To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
100 At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded
101 at this point, iow, both are registered in the type map and both and a NULL parent. This means
102 that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
104 To fix that what we do is to record all generic instantes created while resolving the parent of
105 any generic type definition and, after resolved, correct the parent field if needed.
108 static int record_gclass_instantiation;
109 static GSList *gclass_recorded_list;
110 typedef gboolean (*gclass_record_func) (MonoClass*, void*);
112 /* This TLS variable points to a GSList of classes which have setup_fields () executing */
113 static MonoNativeTlsKey setup_fields_tls_id;
115 static MonoNativeTlsKey init_pending_tls_id;
120 mono_locks_os_acquire (&classes_mutex, ClassesLock);
124 classes_unlock (void)
126 mono_locks_os_release (&classes_mutex, ClassesLock);
130 * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
133 enable_gclass_recording (void)
135 ++record_gclass_instantiation;
139 * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
142 disable_gclass_recording (gclass_record_func func, void *user_data)
144 GSList **head = &gclass_recorded_list;
146 g_assert (record_gclass_instantiation > 0);
147 --record_gclass_instantiation;
150 GSList *node = *head;
151 if (func ((MonoClass*)node->data, user_data)) {
153 g_slist_free_1 (node);
159 /* We automatically discard all recorded gclasses when disabled. */
160 if (!record_gclass_instantiation && gclass_recorded_list) {
161 g_slist_free (gclass_recorded_list);
162 gclass_recorded_list = NULL;
167 * mono_class_from_typeref:
168 * @image: a MonoImage
169 * @type_token: a TypeRef token
171 * Creates the MonoClass* structure representing the type defined by
172 * the typeref token valid inside @image.
173 * Returns: The MonoClass* representing the typeref token, NULL ifcould
177 mono_class_from_typeref (MonoImage *image, guint32 type_token)
180 MonoClass *klass = mono_class_from_typeref_checked (image, type_token, &error);
181 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
186 * mono_class_from_typeref_checked:
187 * @image: a MonoImage
188 * @type_token: a TypeRef token
189 * @error: error return code, if any.
191 * Creates the MonoClass* structure representing the type defined by
192 * the typeref token valid inside @image.
194 * Returns: The MonoClass* representing the typeref token, NULL if it could
195 * not be loaded with the @error value filled with the information about the
199 mono_class_from_typeref_checked (MonoImage *image, guint32 type_token, MonoError *error)
201 guint32 cols [MONO_TYPEREF_SIZE];
202 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
204 const char *name, *nspace;
205 MonoClass *res = NULL;
208 mono_error_init (error);
210 if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, error))
213 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
215 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
216 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
218 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
219 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
220 case MONO_RESOLUTION_SCOPE_MODULE:
222 LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
223 This is not the observed behavior of existing implementations.
224 The defacto behavior is that it's just a typedef in disguise.
226 /* a typedef in disguise */
227 res = mono_class_from_name_checked (image, nspace, name, error);
230 case MONO_RESOLUTION_SCOPE_MODULEREF:
231 module = mono_image_load_module_checked (image, idx, error);
233 res = mono_class_from_name_checked (module, nspace, name, error);
236 case MONO_RESOLUTION_SCOPE_TYPEREF: {
237 MonoClass *enclosing;
240 if (idx == mono_metadata_token_index (type_token)) {
241 mono_error_set_bad_image (error, image, "Image with self-referencing typeref token %08x.", type_token);
245 enclosing = mono_class_from_typeref_checked (image, MONO_TOKEN_TYPE_REF | idx, error);
246 return_val_if_nok (error, NULL);
248 MonoClassExt *ext = mono_class_get_ext (enclosing);
249 if (enclosing->nested_classes_inited && ext) {
250 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
251 for (tmp = ext->nested_classes; tmp; tmp = tmp->next) {
252 res = (MonoClass *)tmp->data;
253 if (strcmp (res->name, name) == 0)
257 /* Don't call mono_class_init as we might've been called by it recursively */
258 int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
260 guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
261 guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
262 const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
264 if (strcmp (nname, name) == 0)
265 return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, error);
267 i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
270 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name);
273 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
277 if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) {
278 mono_error_set_bad_image (error, image, "Image with invalid assemblyref token %08x.", idx);
282 if (!image->references || !image->references [idx - 1])
283 mono_assembly_load_reference (image, idx - 1);
284 g_assert (image->references [idx - 1]);
286 /* If the assembly did not load, register this as a type load exception */
287 if (image->references [idx - 1] == REFERENCE_MISSING){
288 MonoAssemblyName aname;
291 mono_assembly_get_assemblyref (image, idx - 1, &aname);
292 human_name = mono_stringify_assembly_name (&aname);
293 mono_error_set_assembly_load_simple (error, human_name, image->assembly ? image->assembly->ref_only : FALSE);
297 res = mono_class_from_name_checked (image->references [idx - 1]->image, nspace, name, error);
300 /* Generic case, should be avoided for when a better error is possible. */
301 if (!res && mono_error_ok (error)) {
302 char *name = mono_class_name_from_token (image, type_token);
303 char *assembly = mono_assembly_name_from_token (image, type_token);
304 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
311 mono_image_memdup (MonoImage *image, void *data, guint size)
313 void *res = mono_image_alloc (image, size);
314 memcpy (res, data, size);
318 /* Copy everything mono_metadata_free_array free. */
320 mono_dup_array_type (MonoImage *image, MonoArrayType *a)
323 a = (MonoArrayType *)mono_image_memdup (image, a, sizeof (MonoArrayType));
325 a->sizes = (int *)mono_image_memdup (image, a->sizes, a->numsizes * sizeof (int));
327 a->lobounds = (int *)mono_image_memdup (image, a->lobounds, a->numlobounds * sizeof (int));
329 a = (MonoArrayType *)g_memdup (a, sizeof (MonoArrayType));
331 a->sizes = (int *)g_memdup (a->sizes, a->numsizes * sizeof (int));
333 a->lobounds = (int *)g_memdup (a->lobounds, a->numlobounds * sizeof (int));
338 /* Copy everything mono_metadata_free_method_signature free. */
340 mono_metadata_signature_deep_dup (MonoImage *image, MonoMethodSignature *sig)
344 sig = mono_metadata_signature_dup_full (image, sig);
346 sig->ret = mono_metadata_type_dup (image, sig->ret);
347 for (i = 0; i < sig->param_count; ++i)
348 sig->params [i] = mono_metadata_type_dup (image, sig->params [i]);
354 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
356 MonoAssembly *ta = klass->image->assembly;
359 name = mono_stringify_assembly_name (&ta->aname);
360 g_string_append_printf (str, ", %s", name);
365 mono_type_name_check_byref (MonoType *type, GString *str)
368 g_string_append_c (str, '&');
372 * mono_identifier_escape_type_name_chars:
373 * @str: a destination string
374 * @identifier: an IDENTIFIER in internal form
378 * The displayed form of the identifier is appended to str.
380 * The displayed form of an identifier has the characters ,+&*[]\
381 * that have special meaning in type names escaped with a preceeding
382 * backslash (\) character.
385 mono_identifier_escape_type_name_chars (GString* str, const char* identifier)
391 // reserve space for common case: there will be no escaped characters.
392 g_string_set_size(str, n + strlen(identifier));
393 g_string_set_size(str, n);
395 for (const char* s = identifier; *s != 0 ; s++) {
404 g_string_append_c (str, '\\');
405 g_string_append_c (str, *s);
408 g_string_append_c (str, *s);
416 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
417 MonoTypeNameFormat format)
421 switch (type->type) {
422 case MONO_TYPE_ARRAY: {
423 int i, rank = type->data.array->rank;
424 MonoTypeNameFormat nested_format;
426 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
427 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
429 mono_type_get_name_recurse (
430 &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
431 g_string_append_c (str, '[');
433 g_string_append_c (str, '*');
434 for (i = 1; i < rank; i++)
435 g_string_append_c (str, ',');
436 g_string_append_c (str, ']');
438 mono_type_name_check_byref (type, str);
440 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
441 _mono_type_get_assembly_name (type->data.array->eklass, str);
444 case MONO_TYPE_SZARRAY: {
445 MonoTypeNameFormat nested_format;
447 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
448 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
450 mono_type_get_name_recurse (
451 &type->data.klass->byval_arg, str, FALSE, nested_format);
452 g_string_append (str, "[]");
454 mono_type_name_check_byref (type, str);
456 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
457 _mono_type_get_assembly_name (type->data.klass, str);
460 case MONO_TYPE_PTR: {
461 MonoTypeNameFormat nested_format;
463 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
464 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
466 mono_type_get_name_recurse (
467 type->data.type, str, FALSE, nested_format);
468 g_string_append_c (str, '*');
470 mono_type_name_check_byref (type, str);
472 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
473 _mono_type_get_assembly_name (mono_class_from_mono_type (type->data.type), str);
478 if (!mono_generic_param_info (type->data.generic_param))
479 g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num);
481 g_string_append (str, mono_generic_param_info (type->data.generic_param)->name);
483 mono_type_name_check_byref (type, str);
487 klass = mono_class_from_mono_type (type);
488 if (klass->nested_in) {
489 mono_type_get_name_recurse (
490 &klass->nested_in->byval_arg, str, TRUE, format);
491 if (format == MONO_TYPE_NAME_FORMAT_IL)
492 g_string_append_c (str, '.');
494 g_string_append_c (str, '+');
495 } else if (*klass->name_space) {
496 if (format == MONO_TYPE_NAME_FORMAT_IL)
497 g_string_append (str, klass->name_space);
499 mono_identifier_escape_type_name_chars (str, klass->name_space);
500 g_string_append_c (str, '.');
502 if (format == MONO_TYPE_NAME_FORMAT_IL) {
503 char *s = strchr (klass->name, '`');
504 int len = s ? s - klass->name : strlen (klass->name);
505 g_string_append_len (str, klass->name, len);
507 mono_identifier_escape_type_name_chars (str, klass->name);
511 if (mono_class_is_ginst (klass)) {
512 MonoGenericClass *gclass = mono_class_get_generic_class (klass);
513 MonoGenericInst *inst = gclass->context.class_inst;
514 MonoTypeNameFormat nested_format;
517 nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
518 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
520 if (format == MONO_TYPE_NAME_FORMAT_IL)
521 g_string_append_c (str, '<');
523 g_string_append_c (str, '[');
524 for (i = 0; i < inst->type_argc; i++) {
525 MonoType *t = inst->type_argv [i];
528 g_string_append_c (str, ',');
529 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
530 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
531 g_string_append_c (str, '[');
532 mono_type_get_name_recurse (inst->type_argv [i], str, FALSE, nested_format);
533 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
534 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
535 g_string_append_c (str, ']');
537 if (format == MONO_TYPE_NAME_FORMAT_IL)
538 g_string_append_c (str, '>');
540 g_string_append_c (str, ']');
541 } else if (mono_class_is_gtd (klass) &&
542 (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
543 (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
546 if (format == MONO_TYPE_NAME_FORMAT_IL)
547 g_string_append_c (str, '<');
549 g_string_append_c (str, '[');
550 for (i = 0; i < mono_class_get_generic_container (klass)->type_argc; i++) {
552 g_string_append_c (str, ',');
553 g_string_append (str, mono_generic_container_get_param_info (mono_class_get_generic_container (klass), i)->name);
555 if (format == MONO_TYPE_NAME_FORMAT_IL)
556 g_string_append_c (str, '>');
558 g_string_append_c (str, ']');
561 mono_type_name_check_byref (type, str);
563 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
564 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
565 _mono_type_get_assembly_name (klass, str);
571 * mono_type_get_name_full:
573 * @format: the format for the return string.
576 * Returns: The string representation in a number of formats:
578 * if format is MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
579 * returned in the formatrequired by System.Reflection, this is the
580 * inverse of mono_reflection_parse_type ().
582 * if format is MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
583 * be used by the IL assembler.
585 * if format is MONO_TYPE_NAME_FORMAT_FULL_NAME
587 * if format is MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
590 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
594 result = g_string_new ("");
596 mono_type_get_name_recurse (type, result, FALSE, format);
598 return g_string_free (result, FALSE);
602 * mono_type_get_full_name:
605 * Returns: The string representation for type as required by System.Reflection.
606 * The inverse of mono_reflection_parse_type ().
609 mono_type_get_full_name (MonoClass *klass)
611 return mono_type_get_name_full (mono_class_get_type (klass), MONO_TYPE_NAME_FORMAT_REFLECTION);
615 * mono_type_get_name:
618 * Returns: The string representation for type as it would be represented in IL code.
621 mono_type_get_name (MonoType *type)
623 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
627 * mono_type_get_underlying_type:
630 * Returns: The MonoType for the underlying integer type if @type
631 * is an enum and byref is false, otherwise the type itself.
634 mono_type_get_underlying_type (MonoType *type)
636 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype && !type->byref)
637 return mono_class_enum_basetype (type->data.klass);
638 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype && !type->byref)
639 return mono_class_enum_basetype (type->data.generic_class->container_class);
644 * mono_class_is_open_constructed_type:
647 * Returns: TRUE if type represents a generics open constructed type.
648 * IOW, not all type parameters required for the instantiation have
649 * been provided or it's a generic type definition.
651 * An open constructed type means it's a non realizable type. Not to
652 * be mixed up with an abstract type - we can't cast or dispatch to
653 * an open type, for example.
656 mono_class_is_open_constructed_type (MonoType *t)
662 case MONO_TYPE_SZARRAY:
663 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
664 case MONO_TYPE_ARRAY:
665 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
667 return mono_class_is_open_constructed_type (t->data.type);
668 case MONO_TYPE_GENERICINST:
669 return t->data.generic_class->context.class_inst->is_open;
670 case MONO_TYPE_CLASS:
671 case MONO_TYPE_VALUETYPE:
672 return mono_class_is_gtd (t->data.klass);
679 This is a simple function to catch the most common bad instances of generic types.
680 Specially those that might lead to further failures in the runtime.
683 is_valid_generic_argument (MonoType *type)
685 switch (type->type) {
687 //case MONO_TYPE_TYPEDBYREF:
695 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
697 mono_error_init (error);
699 switch (type->type) {
700 case MONO_TYPE_MVAR: {
702 int num = mono_type_get_generic_param_num (type);
703 MonoGenericInst *inst = context->method_inst;
706 if (num >= inst->type_argc) {
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 in this context with %d instantiations",
709 num, info ? info->name : "", inst->type_argc);
713 if (!is_valid_generic_argument (inst->type_argv [num])) {
714 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
715 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
716 num, info ? info->name : "", inst->type_argv [num]->type);
720 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
721 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
722 * ->byref and ->attrs from @type are propagated to the returned type.
724 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
725 nt->byref = type->byref;
726 nt->attrs = type->attrs;
729 case MONO_TYPE_VAR: {
731 int num = mono_type_get_generic_param_num (type);
732 MonoGenericInst *inst = context->class_inst;
735 if (num >= inst->type_argc) {
736 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
737 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
738 num, info ? info->name : "", inst->type_argc);
741 if (!is_valid_generic_argument (inst->type_argv [num])) {
742 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
743 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
744 num, info ? info->name : "", inst->type_argv [num]->type);
747 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
748 nt->byref = type->byref;
749 nt->attrs = type->attrs;
752 case MONO_TYPE_SZARRAY: {
753 MonoClass *eclass = type->data.klass;
754 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
755 if (!inflated || !mono_error_ok (error))
757 nt = mono_metadata_type_dup (image, type);
758 nt->data.klass = mono_class_from_mono_type (inflated);
759 mono_metadata_free_type (inflated);
762 case MONO_TYPE_ARRAY: {
763 MonoClass *eclass = type->data.array->eklass;
764 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
765 if (!inflated || !mono_error_ok (error))
767 nt = mono_metadata_type_dup (image, type);
768 nt->data.array->eklass = mono_class_from_mono_type (inflated);
769 mono_metadata_free_type (inflated);
772 case MONO_TYPE_GENERICINST: {
773 MonoGenericClass *gclass = type->data.generic_class;
774 MonoGenericInst *inst;
776 if (!gclass->context.class_inst->is_open)
779 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
780 return_val_if_nok (error, NULL);
782 if (inst != gclass->context.class_inst)
783 gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
785 if (gclass == type->data.generic_class)
788 nt = mono_metadata_type_dup (image, type);
789 nt->data.generic_class = gclass;
792 case MONO_TYPE_CLASS:
793 case MONO_TYPE_VALUETYPE: {
794 MonoClass *klass = type->data.klass;
795 MonoGenericContainer *container = mono_class_try_get_generic_container (klass);
796 MonoGenericInst *inst;
797 MonoGenericClass *gclass = NULL;
803 /* We can't use context->class_inst directly, since it can have more elements */
804 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
805 return_val_if_nok (error, NULL);
807 if (inst == container->context.class_inst)
810 gclass = mono_metadata_lookup_generic_class (klass, inst, image_is_dynamic (klass->image));
812 nt = mono_metadata_type_dup (image, type);
813 nt->type = MONO_TYPE_GENERICINST;
814 nt->data.generic_class = gclass;
824 mono_generic_class_get_context (MonoGenericClass *gclass)
826 return &gclass->context;
830 mono_class_get_context (MonoClass *klass)
832 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
833 return gklass ? mono_generic_class_get_context (gklass) : NULL;
837 * mono_class_inflate_generic_type_with_mempool:
838 * @mempool: a mempool
840 * @context: a generics context
841 * @error: error context
843 * The same as mono_class_inflate_generic_type, but allocates the MonoType
844 * from mempool if it is non-NULL. If it is NULL, the MonoType is
845 * allocated on the heap and is owned by the caller.
846 * The returned type can potentially be the same as TYPE, so it should not be
847 * modified by the caller, and it should be freed using mono_metadata_free_type ().
850 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
852 MonoType *inflated = NULL;
853 mono_error_init (error);
856 inflated = inflate_generic_type (image, type, context, error);
857 return_val_if_nok (error, NULL);
860 MonoType *shared = mono_metadata_get_shared_type (type);
865 return mono_metadata_type_dup (image, type);
869 mono_stats.inflated_type_count++;
874 * mono_class_inflate_generic_type:
876 * @context: a generics context
878 * If @type is a generic type and @context is not NULL, instantiate it using the
879 * generics context @context.
881 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
882 * on the heap and is owned by the caller. Returns NULL on error.
884 * @deprecated Please use mono_class_inflate_generic_type_checked instead
887 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
891 result = mono_class_inflate_generic_type_checked (type, context, &error);
892 mono_error_cleanup (&error);
897 * mono_class_inflate_generic_type:
899 * @context: a generics context
900 * @error: error context to use
902 * If @type is a generic type and @context is not NULL, instantiate it using the
903 * generics context @context.
905 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
906 * on the heap and is owned by the caller.
909 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
911 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
915 * mono_class_inflate_generic_type_no_copy:
917 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
921 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
923 MonoType *inflated = NULL;
925 mono_error_init (error);
927 inflated = inflate_generic_type (image, type, context, error);
928 return_val_if_nok (error, NULL);
934 mono_stats.inflated_type_count++;
939 * mono_class_inflate_generic_class:
941 * Inflate the class @gklass with @context. Set @error on failure.
944 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
949 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
950 return_val_if_nok (error, NULL);
952 res = mono_class_from_mono_type (inflated);
953 mono_metadata_free_type (inflated);
958 static MonoGenericContext
959 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
961 MonoGenericInst *class_inst = NULL;
962 MonoGenericInst *method_inst = NULL;
963 MonoGenericContext res = { NULL, NULL };
965 mono_error_init (error);
967 if (context->class_inst) {
968 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
969 if (!mono_error_ok (error))
973 if (context->method_inst) {
974 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
975 if (!mono_error_ok (error))
979 res.class_inst = class_inst;
980 res.method_inst = method_inst;
986 * mono_class_inflate_generic_method:
987 * @method: a generic method
988 * @context: a generics context
990 * Instantiate the generic method @method using the generics context @context.
992 * Returns: The new instantiated method
995 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
997 return mono_class_inflate_generic_method_full (method, NULL, context);
1001 mono_class_inflate_generic_method_checked (MonoMethod *method, MonoGenericContext *context, MonoError *error)
1003 return mono_class_inflate_generic_method_full_checked (method, NULL, context, error);
1007 * mono_class_inflate_generic_method_full:
1009 * Instantiate method @method with the generic context @context.
1010 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
1011 * Use mono_method_signature () and mono_method_get_header () to get the correct values.
1014 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
1017 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
1018 if (!mono_error_ok (&error))
1019 /*FIXME do proper error handling - on this case, kill this function. */
1020 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
1026 * mono_class_inflate_generic_method_full_checked:
1027 * Same as mono_class_inflate_generic_method_full but return failure using @error.
1030 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
1033 MonoMethodInflated *iresult, *cached;
1034 MonoMethodSignature *sig;
1035 MonoGenericContext tmp_context;
1037 mono_error_init (error);
1039 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1040 while (method->is_inflated) {
1041 MonoGenericContext *method_context = mono_method_get_context (method);
1042 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1044 tmp_context = inflate_generic_context (method_context, context, error);
1045 return_val_if_nok (error, NULL);
1047 context = &tmp_context;
1049 if (mono_metadata_generic_context_equal (method_context, context))
1052 method = imethod->declaring;
1056 * A method only needs to be inflated if the context has argument for which it is
1059 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1060 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1063 if (!((method->is_generic && context->method_inst) ||
1064 (mono_class_is_gtd (method->klass) && context->class_inst)))
1067 iresult = g_new0 (MonoMethodInflated, 1);
1068 iresult->context = *context;
1069 iresult->declaring = method;
1071 if (!context->method_inst && method->is_generic)
1072 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1074 if (!context->class_inst) {
1075 g_assert (!mono_class_is_ginst (iresult->declaring->klass));
1076 if (mono_class_is_gtd (iresult->declaring->klass))
1077 iresult->context.class_inst = mono_class_get_generic_container (iresult->declaring->klass)->context.class_inst;
1079 /* This can happen with some callers like mono_object_get_virtual_method () */
1080 if (!mono_class_is_gtd (iresult->declaring->klass) && !mono_class_is_ginst (iresult->declaring->klass))
1081 iresult->context.class_inst = NULL;
1083 MonoImageSet *set = mono_metadata_get_image_set_for_method (iresult);
1086 mono_image_set_lock (set);
1087 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1088 mono_image_set_unlock (set);
1092 return (MonoMethod*)cached;
1095 mono_stats.inflated_method_count++;
1097 inflated_methods_size += sizeof (MonoMethodInflated);
1099 sig = mono_method_signature (method);
1101 char *name = mono_type_get_full_name (method->klass);
1102 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1108 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1110 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1113 result = (MonoMethod *) iresult;
1114 result->is_inflated = TRUE;
1115 result->is_generic = FALSE;
1116 result->sre_method = FALSE;
1117 result->signature = NULL;
1119 if (method->wrapper_type) {
1120 MonoMethodWrapper *mw = (MonoMethodWrapper*)method;
1121 MonoMethodWrapper *resw = (MonoMethodWrapper*)result;
1122 int len = GPOINTER_TO_INT (((void**)mw->method_data) [0]);
1124 resw->method_data = (void **)g_malloc (sizeof (gpointer) * (len + 1));
1125 memcpy (resw->method_data, mw->method_data, sizeof (gpointer) * (len + 1));
1128 if (iresult->context.method_inst) {
1129 /* Set the generic_container of the result to the generic_container of method */
1130 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1132 if (generic_container && iresult->context.method_inst == generic_container->context.method_inst) {
1133 result->is_generic = 1;
1134 mono_method_set_generic_container (result, generic_container);
1139 MonoGenericClass *gklass_hint = mono_class_try_get_generic_class (klass_hint);
1140 if (gklass_hint && (gklass_hint->container_class != method->klass || gklass_hint->context.class_inst != context->class_inst))
1144 if (mono_class_is_gtd (method->klass))
1145 result->klass = klass_hint;
1147 if (!result->klass) {
1148 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1149 if (!mono_error_ok (error))
1152 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1154 mono_metadata_free_type (inflated);
1158 * FIXME: This should hold, but it doesn't:
1160 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1161 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1162 * g_assert (result->is_generic);
1165 * Fixing this here causes other things to break, hence a very
1166 * ugly hack in mini-trampolines.c - see
1167 * is_generic_method_definition().
1171 mono_image_set_lock (set);
1172 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1174 g_hash_table_insert (set->gmethod_cache, iresult, iresult);
1175 iresult->owner = set;
1178 mono_image_set_unlock (set);
1180 return (MonoMethod*)cached;
1188 * mono_get_inflated_method:
1190 * Obsolete. We keep it around since it's mentioned in the public API.
1193 mono_get_inflated_method (MonoMethod *method)
1199 * mono_method_get_context_general:
1201 * @uninflated: handle uninflated methods?
1203 * Returns the generic context of a method or NULL if it doesn't have
1204 * one. For an inflated method that's the context stored in the
1205 * method. Otherwise it's in the method's generic container or in the
1206 * generic container of the method's class.
1209 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1211 if (method->is_inflated) {
1212 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1213 return &imethod->context;
1217 if (method->is_generic)
1218 return &(mono_method_get_generic_container (method)->context);
1219 if (mono_class_is_gtd (method->klass))
1220 return &mono_class_get_generic_container (method->klass)->context;
1225 * mono_method_get_context:
1228 * Returns the generic context for method if it's inflated, otherwise
1232 mono_method_get_context (MonoMethod *method)
1234 return mono_method_get_context_general (method, FALSE);
1238 * mono_method_get_generic_container:
1240 * Returns the generic container of METHOD, which should be a generic method definition.
1241 * Returns NULL if METHOD is not a generic method definition.
1242 * LOCKING: Acquires the loader lock.
1244 MonoGenericContainer*
1245 mono_method_get_generic_container (MonoMethod *method)
1247 MonoGenericContainer *container;
1249 if (!method->is_generic)
1252 container = (MonoGenericContainer *)mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1253 g_assert (container);
1259 * mono_method_set_generic_container:
1261 * Sets the generic container of METHOD to CONTAINER.
1262 * LOCKING: Acquires the image lock.
1265 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1267 g_assert (method->is_generic);
1269 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1273 * mono_class_find_enum_basetype:
1274 * @class: The enum class
1276 * Determine the basetype of an enum by iterating through its fields. We do this
1277 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1280 mono_class_find_enum_basetype (MonoClass *klass, MonoError *error)
1282 MonoGenericContainer *container = NULL;
1283 MonoImage *m = klass->image;
1284 const int top = mono_class_get_field_count (klass);
1285 int i, first_field_idx;
1287 g_assert (klass->enumtype);
1289 mono_error_init (error);
1291 container = mono_class_try_get_generic_container (klass);
1292 if (mono_class_is_ginst (klass)) {
1293 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
1295 container = mono_class_get_generic_container (gklass);
1296 g_assert (container);
1300 * Fetch all the field information.
1302 first_field_idx = mono_class_get_first_field_idx (klass);
1303 for (i = 0; i < top; i++){
1305 guint32 cols [MONO_FIELD_SIZE];
1306 int idx = first_field_idx + i;
1309 /* first_field_idx and idx points into the fieldptr table */
1310 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1312 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1315 if (!mono_verifier_verify_field_signature (klass->image, cols [MONO_FIELD_SIGNATURE], NULL)) {
1316 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x", cols [MONO_FIELD_SIGNATURE]);
1320 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1321 mono_metadata_decode_value (sig, &sig);
1322 /* FIELD signature == 0x06 */
1324 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig);
1328 ftype = mono_metadata_parse_type_checked (m, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
1332 if (mono_class_is_ginst (klass)) {
1333 //FIXME do we leak here?
1334 ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (klass), error);
1335 if (!mono_error_ok (error))
1337 ftype->attrs = cols [MONO_FIELD_FLAGS];
1342 mono_error_set_type_load_class (error, klass, "Could not find base type");
1349 * Checks for MonoClass::has_failure without resolving all MonoType's into MonoClass'es
1352 mono_type_has_exceptions (MonoType *type)
1354 switch (type->type) {
1355 case MONO_TYPE_CLASS:
1356 case MONO_TYPE_VALUETYPE:
1357 case MONO_TYPE_SZARRAY:
1358 return mono_class_has_failure (type->data.klass);
1359 case MONO_TYPE_ARRAY:
1360 return mono_class_has_failure (type->data.array->eklass);
1361 case MONO_TYPE_GENERICINST:
1362 return mono_class_has_failure (mono_generic_class_get_class (type->data.generic_class));
1369 mono_error_set_for_class_failure (MonoError *oerror, const MonoClass *klass)
1371 g_assert (mono_class_has_failure (klass));
1372 MonoErrorBoxed *box = (MonoErrorBoxed*)mono_class_get_exception_data (klass);
1373 mono_error_set_from_boxed (oerror, box);
1380 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1384 mono_class_alloc (MonoClass *klass, int size)
1386 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
1388 return mono_image_set_alloc (gklass->owner, size);
1390 return mono_image_alloc (klass->image, size);
1394 mono_class_alloc0 (MonoClass *klass, int size)
1398 res = mono_class_alloc (klass, size);
1399 memset (res, 0, size);
1403 #define mono_class_new0(klass,struct_type, n_structs) \
1404 ((struct_type *) mono_class_alloc0 ((klass), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1407 * mono_class_setup_basic_field_info:
1408 * @class: The class to initialize
1410 * Initializes the following fields in MonoClass:
1411 * * klass->fields (only field->parent and field->name)
1412 * * klass->field.count
1413 * * klass->first_field_idx
1414 * LOCKING: Acquires the loader lock
1417 mono_class_setup_basic_field_info (MonoClass *klass)
1419 MonoGenericClass *gklass;
1420 MonoClassField *field;
1421 MonoClassField *fields;
1429 gklass = mono_class_try_get_generic_class (klass);
1430 gtd = gklass ? mono_class_get_generic_type_definition (klass) : NULL;
1431 image = klass->image;
1434 if (gklass && image_is_dynamic (gklass->container_class->image) && !gklass->container_class->wastypebuilder) {
1436 * This happens when a generic instance of an unfinished generic typebuilder
1437 * is used as an element type for creating an array type. We can't initialize
1438 * the fields of this class using the fields of gklass, since gklass is not
1439 * finished yet, fields could be added to it later.
1445 mono_class_setup_basic_field_info (gtd);
1447 mono_loader_lock ();
1448 mono_class_set_field_count (klass, mono_class_get_field_count (gtd));
1449 mono_loader_unlock ();
1452 top = mono_class_get_field_count (klass);
1454 fields = (MonoClassField *)mono_class_alloc0 (klass, sizeof (MonoClassField) * top);
1457 * Fetch all the field information.
1459 int first_field_idx = mono_class_has_static_metadata (klass) ? mono_class_get_first_field_idx (klass) : 0;
1460 for (i = 0; i < top; i++) {
1461 field = &fields [i];
1462 field->parent = klass;
1465 field->name = mono_field_get_name (>d->fields [i]);
1467 int idx = first_field_idx + i;
1468 /* first_field_idx and idx points into the fieldptr table */
1469 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1470 /* The name is needed for fieldrefs */
1471 field->name = mono_metadata_string_heap (image, name_idx);
1475 mono_memory_barrier ();
1477 mono_loader_lock ();
1479 klass->fields = fields;
1480 mono_loader_unlock ();
1484 * mono_class_set_failure_causedby_class:
1485 * @klass: the class that is failing
1486 * @caused_by: the class that caused the failure
1487 * @msg: Why @klass is failing.
1489 * If @caused_by has a failure, sets a TypeLoadException failure on
1490 * @klass with message "@msg, due to: {@caused_by message}".
1492 * Returns: TRUE if a failiure was set, or FALSE if @caused_by doesn't have a failure.
1495 mono_class_set_type_load_failure_causedby_class (MonoClass *klass, const MonoClass *caused_by, const gchar* msg)
1497 if (mono_class_has_failure (caused_by)) {
1498 MonoError cause_error;
1499 mono_error_init (&cause_error);
1500 mono_error_set_for_class_failure (&cause_error, caused_by);
1501 mono_class_set_type_load_failure (klass, "%s, due to: %s", msg, mono_error_get_message (&cause_error));
1502 mono_error_cleanup (&cause_error);
1511 * mono_class_setup_fields:
1512 * @klass: The class to initialize
1514 * Initializes klass->fields, computes class layout and sizes.
1515 * typebuilder_setup_fields () is the corresponding function for dynamic classes.
1516 * Sets the following fields in @klass:
1517 * - all the fields initialized by mono_class_init_sizes ()
1518 * - element_class/cast_class (for enums)
1519 * - field->type/offset for all fields
1522 * LOCKING: Acquires the loader lock.
1525 mono_class_setup_fields (MonoClass *klass)
1528 MonoImage *m = klass->image;
1530 guint32 layout = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK;
1532 guint32 real_size = 0;
1533 guint32 packing_size = 0;
1535 gboolean explicit_size;
1536 MonoClassField *field;
1537 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
1538 MonoClass *gtd = gklass ? mono_class_get_generic_type_definition (klass) : NULL;
1540 if (klass->fields_inited)
1543 if (gklass && image_is_dynamic (gklass->container_class->image) && !gklass->container_class->wastypebuilder) {
1545 * This happens when a generic instance of an unfinished generic typebuilder
1546 * is used as an element type for creating an array type. We can't initialize
1547 * the fields of this class using the fields of gklass, since gklass is not
1548 * finished yet, fields could be added to it later.
1553 mono_class_setup_basic_field_info (klass);
1554 top = mono_class_get_field_count (klass);
1557 mono_class_setup_fields (gtd);
1558 if (mono_class_set_type_load_failure_causedby_class (klass, gtd, "Generic type definition failed"))
1563 if (klass->parent) {
1564 /* For generic instances, klass->parent might not have been initialized */
1565 mono_class_init (klass->parent);
1566 mono_class_setup_fields (klass->parent);
1567 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Could not set up parent class"))
1569 instance_size = klass->parent->instance_size;
1571 instance_size = sizeof (MonoObject);
1574 /* Get the real size */
1575 explicit_size = mono_metadata_packing_from_typedef (klass->image, klass->type_token, &packing_size, &real_size);
1577 instance_size += real_size;
1580 * This function can recursively call itself.
1581 * Prevent infinite recursion by using a list in TLS.
1583 GSList *init_list = (GSList *)mono_native_tls_get_value (setup_fields_tls_id);
1584 if (g_slist_find (init_list, klass))
1586 init_list = g_slist_prepend (init_list, klass);
1587 mono_native_tls_set_value (setup_fields_tls_id, init_list);
1590 * Fetch all the field information.
1592 int first_field_idx = mono_class_has_static_metadata (klass) ? mono_class_get_first_field_idx (klass) : 0;
1593 for (i = 0; i < top; i++) {
1594 int idx = first_field_idx + i;
1595 field = &klass->fields [i];
1598 mono_field_resolve_type (field, &error);
1599 if (!mono_error_ok (&error)) {
1600 /*mono_field_resolve_type already failed class*/
1601 mono_error_cleanup (&error);
1605 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(klass), field->name);
1606 g_assert (field->type);
1609 if (mono_field_is_deleted (field))
1611 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1613 mono_metadata_field_info (m, idx, &uoffset, NULL, NULL);
1614 int offset = uoffset;
1616 if (offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1617 mono_class_set_type_load_failure (klass, "Missing field layout info for %s", field->name);
1620 if (offset < -1) { /*-1 is used to encode special static fields */
1621 mono_class_set_type_load_failure (klass, "Field '%s' has a negative offset %d", field->name, offset);
1624 if (mono_class_is_gtd (klass)) {
1625 mono_class_set_type_load_failure (klass, "Generic class cannot have explicit layout.");
1629 if (mono_type_has_exceptions (field->type)) {
1630 char *class_name = mono_type_get_full_name (klass);
1631 char *type_name = mono_type_full_name (field->type);
1633 mono_class_set_type_load_failure (klass, "");
1634 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1635 g_free (class_name);
1639 /* The def_value of fields is compute lazily during vtable creation */
1642 if (!mono_class_has_failure (klass)) {
1643 mono_loader_lock ();
1644 mono_class_layout_fields (klass, instance_size, packing_size, FALSE);
1645 mono_loader_unlock ();
1648 init_list = g_slist_remove (init_list, klass);
1649 mono_native_tls_set_value (setup_fields_tls_id, init_list);
1653 init_sizes_with_info (MonoClass *klass, MonoCachedClassInfo *cached_info)
1656 klass->instance_size = cached_info->instance_size;
1657 klass->sizes.class_size = cached_info->class_size;
1658 klass->packing_size = cached_info->packing_size;
1659 klass->min_align = cached_info->min_align;
1660 klass->blittable = cached_info->blittable;
1661 klass->has_references = cached_info->has_references;
1662 klass->has_static_refs = cached_info->has_static_refs;
1663 klass->no_special_static_fields = cached_info->no_special_static_fields;
1666 if (!klass->size_inited)
1667 mono_class_setup_fields (klass);
1672 * mono_class_init_sizes:
1674 * Initializes the size related fields of @klass without loading all field data if possible.
1675 * Sets the following fields in @klass:
1677 * - sizes.class_size
1684 * Can fail the class.
1686 * LOCKING: Acquires the loader lock.
1689 mono_class_init_sizes (MonoClass *klass)
1691 MonoCachedClassInfo cached_info;
1692 gboolean has_cached_info;
1694 if (klass->size_inited)
1697 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
1699 init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
1703 * mono_type_get_basic_type_from_generic:
1706 * Returns a closed type corresponding to the possibly open type
1710 mono_type_get_basic_type_from_generic (MonoType *type)
1712 /* When we do generic sharing we let type variables stand for reference/primitive types. */
1713 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) &&
1714 (!type->data.generic_param->gshared_constraint || type->data.generic_param->gshared_constraint->type == MONO_TYPE_OBJECT))
1715 return &mono_defaults.object_class->byval_arg;
1720 class_has_references (MonoClass *klass)
1722 mono_class_init_sizes (klass);
1725 * has_references is not set if this is called recursively, but this is not a problem since this is only used
1726 * during field layout, and instance fields are initialized before static fields, and instance fields can't
1729 return klass->has_references;
1733 type_has_references (MonoClass *klass, MonoType *ftype)
1735 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (klass, ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && class_has_references (mono_class_from_mono_type (ftype)))))
1737 if (!ftype->byref && (ftype->type == MONO_TYPE_VAR || ftype->type == MONO_TYPE_MVAR)) {
1738 MonoGenericParam *gparam = ftype->data.generic_param;
1740 if (gparam->gshared_constraint)
1741 return class_has_references (mono_class_from_mono_type (gparam->gshared_constraint));
1747 * mono_class_layout_fields:
1749 * @base_instance_size: base instance size
1752 * This contains the common code for computing the layout of classes and sizes.
1753 * This should only be called from mono_class_setup_fields () and
1754 * typebuilder_setup_fields ().
1756 * LOCKING: Acquires the loader lock
1759 mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_size, gboolean sre)
1762 const int top = mono_class_get_field_count (klass);
1763 guint32 layout = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK;
1764 guint32 pass, passes, real_size;
1765 gboolean gc_aware_layout = FALSE;
1766 gboolean has_static_fields = FALSE;
1767 gboolean has_references = FALSE;
1768 gboolean has_static_refs = FALSE;
1769 MonoClassField *field;
1771 int instance_size = base_instance_size;
1772 int class_size, min_align;
1774 gboolean *fields_has_references;
1777 * We want to avoid doing complicated work inside locks, so we compute all the required
1778 * information and write it to @klass inside a lock.
1780 if (klass->fields_inited)
1783 if ((packing_size & 0xffffff00) != 0) {
1784 mono_class_set_type_load_failure (klass, "Could not load struct '%s' with packing size %d >= 256", klass->name, packing_size);
1788 if (klass->parent) {
1789 min_align = klass->parent->min_align;
1790 /* we use | since it may have been set already */
1791 has_references = klass->has_references | klass->parent->has_references;
1795 /* We can't really enable 16 bytes alignment until the GC supports it.
1796 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1797 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1798 Bug #506144 is an example of this issue.
1800 if (klass->simd_type)
1805 * When we do generic sharing we need to have layout
1806 * information for open generic classes (either with a generic
1807 * context containing type variables or with a generic
1808 * container), so we don't return in that case anymore.
1811 if (klass->enumtype) {
1812 for (i = 0; i < top; i++) {
1813 field = &klass->fields [i];
1814 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1815 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
1820 if (!mono_class_enum_basetype (klass)) {
1821 mono_class_set_type_load_failure (klass, "The enumeration's base type is invalid.");
1827 * Enable GC aware auto layout: in this mode, reference
1828 * fields are grouped together inside objects, increasing collector
1830 * Requires that all classes whose layout is known to native code be annotated
1831 * with [StructLayout (LayoutKind.Sequential)]
1832 * Value types have gc_aware_layout disabled by default, as per
1833 * what the default is for other runtimes.
1835 /* corlib is missing [StructLayout] directives in many places */
1836 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1837 if (!klass->valuetype)
1838 gc_aware_layout = TRUE;
1841 /* Compute klass->blittable */
1844 blittable = klass->parent->blittable;
1845 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(mono_is_corlib_image (klass->image) && !strcmp (klass->name_space, "System") && !strcmp (klass->name, "ValueType")) && top)
1847 for (i = 0; i < top; i++) {
1848 field = &klass->fields [i];
1850 if (mono_field_is_deleted (field))
1852 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1855 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1858 MonoClass *field_class = mono_class_from_mono_type (field->type);
1860 mono_class_setup_fields (field_class);
1861 if (mono_class_has_failure (field_class)) {
1862 MonoError field_error;
1863 mono_error_init (&field_error);
1864 mono_error_set_for_class_failure (&field_error, field_class);
1865 mono_class_set_type_load_failure (klass, "Could not set up field '%s' due to: %s", field->name, mono_error_get_message (&field_error));
1866 mono_error_cleanup (&field_error);
1870 if (!field_class || !field_class->blittable)
1874 if (klass->enumtype)
1875 blittable = klass->element_class->blittable;
1877 if (mono_class_has_failure (klass))
1879 if (klass == mono_defaults.string_class)
1882 /* Compute klass->has_references */
1884 * Process non-static fields first, since static fields might recursively
1885 * refer to the class itself.
1887 for (i = 0; i < top; i++) {
1890 field = &klass->fields [i];
1892 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1893 ftype = mono_type_get_underlying_type (field->type);
1894 ftype = mono_type_get_basic_type_from_generic (ftype);
1895 if (type_has_references (klass, ftype))
1896 has_references = TRUE;
1901 * Compute field layout and total size (not considering static fields)
1903 field_offsets = g_new0 (int, top);
1904 fields_has_references = g_new0 (gboolean, top);
1905 int first_field_idx = mono_class_has_static_metadata (klass) ? mono_class_get_first_field_idx (klass) : 0;
1907 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1908 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1909 if (gc_aware_layout)
1914 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1917 if (klass->parent) {
1918 mono_class_setup_fields (klass->parent);
1919 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Cannot initialize parent class"))
1921 real_size = klass->parent->instance_size;
1923 real_size = sizeof (MonoObject);
1926 for (pass = 0; pass < passes; ++pass) {
1927 for (i = 0; i < top; i++){
1932 field = &klass->fields [i];
1934 if (mono_field_is_deleted (field))
1936 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1939 ftype = mono_type_get_underlying_type (field->type);
1940 ftype = mono_type_get_basic_type_from_generic (ftype);
1941 if (gc_aware_layout) {
1942 fields_has_references [i] = type_has_references (klass, ftype);
1943 if (fields_has_references [i]) {
1952 if ((top == 1) && (instance_size == sizeof (MonoObject)) &&
1953 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1954 /* This field is a hack inserted by MCS to empty structures */
1958 size = mono_type_size (field->type, &align);
1960 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1961 align = packing_size ? MIN (packing_size, align): align;
1962 /* if the field has managed references, we need to force-align it
1965 if (type_has_references (klass, ftype))
1966 align = MAX (align, sizeof (gpointer));
1968 min_align = MAX (align, min_align);
1969 field_offsets [i] = real_size;
1971 field_offsets [i] += align - 1;
1972 field_offsets [i] &= ~(align - 1);
1974 /*TypeBuilders produce all sort of weird things*/
1975 g_assert (image_is_dynamic (klass->image) || field_offsets [i] > 0);
1976 real_size = field_offsets [i] + size;
1979 /* Make SIMD types as big as a SIMD register since they can be stored into using simd stores */
1980 if (klass->simd_type)
1981 real_size = MAX (real_size, sizeof (MonoObject) + 16);
1982 instance_size = MAX (real_size, instance_size);
1984 if (instance_size & (min_align - 1)) {
1985 instance_size += min_align - 1;
1986 instance_size &= ~(min_align - 1);
1990 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
1994 for (i = 0; i < top; i++) {
1999 field = &klass->fields [i];
2002 * There must be info about all the fields in a type if it
2003 * uses explicit layout.
2005 if (mono_field_is_deleted (field))
2007 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2010 size = mono_type_size (field->type, &align);
2011 align = packing_size ? MIN (packing_size, align): align;
2012 min_align = MAX (align, min_align);
2015 /* Already set by typebuilder_setup_fields () */
2016 field_offsets [i] = field->offset + sizeof (MonoObject);
2018 int idx = first_field_idx + i;
2020 mono_metadata_field_info (klass->image, idx, &offset, NULL, NULL);
2021 field_offsets [i] = offset + sizeof (MonoObject);
2023 ftype = mono_type_get_underlying_type (field->type);
2024 ftype = mono_type_get_basic_type_from_generic (ftype);
2025 if (type_has_references (klass, ftype)) {
2026 if (field_offsets [i] % sizeof (gpointer)) {
2027 mono_class_set_type_load_failure (klass, "Reference typed field '%s' has explicit offset that is not pointer-size aligned.", field->name);
2034 real_size = MAX (real_size, size + field_offsets [i]);
2037 if (klass->has_references) {
2038 ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
2040 /* Check for overlapping reference and non-reference fields */
2041 for (i = 0; i < top; i++) {
2044 field = &klass->fields [i];
2046 if (mono_field_is_deleted (field))
2048 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2050 ftype = mono_type_get_underlying_type (field->type);
2051 if (MONO_TYPE_IS_REFERENCE (ftype))
2052 ref_bitmap [field_offsets [i] / sizeof (gpointer)] = 1;
2054 for (i = 0; i < top; i++) {
2055 field = &klass->fields [i];
2057 if (mono_field_is_deleted (field))
2059 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2062 // FIXME: Too much code does this
2064 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field_offsets [i] / sizeof (gpointer)]) {
2065 mono_class_set_type_load_failure (klass, "Could not load type '%s' because it contains an object field at offset %d that is incorrectly aligned or overlapped by a non-object field.", klass->name, field_offsets [i]);
2069 g_free (ref_bitmap);
2072 instance_size = MAX (real_size, instance_size);
2073 if (instance_size & (min_align - 1)) {
2074 instance_size += min_align - 1;
2075 instance_size &= ~(min_align - 1);
2081 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2083 * This leads to all kinds of problems with nested structs, so only
2084 * enable it when a MONO_DEBUG property is set.
2086 * For small structs, set min_align to at least the struct size to improve
2087 * performance, and since the JIT memset/memcpy code assumes this and generates
2088 * unaligned accesses otherwise. See #78990 for a testcase.
2090 if (mono_align_small_structs && top) {
2091 if (instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2092 min_align = MAX (min_align, instance_size - sizeof (MonoObject));
2096 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR)
2097 instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
2098 else if (klass->byval_arg.type == MONO_TYPE_PTR)
2099 instance_size = sizeof (MonoObject) + sizeof (gpointer);
2101 /* Publish the data */
2102 mono_loader_lock ();
2103 if (klass->instance_size && !klass->image->dynamic) {
2104 /* Might be already set using cached info */
2105 if (klass->instance_size != instance_size) {
2106 /* Emit info to help debugging */
2107 g_print ("%s\n", mono_class_full_name (klass));
2108 g_print ("%d %d %d %d\n", klass->instance_size, instance_size, klass->blittable, blittable);
2109 g_print ("%d %d %d %d\n", klass->has_references, has_references, klass->packing_size, packing_size);
2110 g_print ("%d %d\n", klass->min_align, min_align);
2111 for (i = 0; i < top; ++i) {
2112 field = &klass->fields [i];
2113 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
2114 printf (" %s %d %d %d\n", klass->fields [i].name, klass->fields [i].offset, field_offsets [i], fields_has_references [i]);
2117 g_assert (klass->instance_size == instance_size);
2119 klass->instance_size = instance_size;
2121 klass->blittable = blittable;
2122 klass->has_references = has_references;
2123 klass->packing_size = packing_size;
2124 klass->min_align = min_align;
2125 for (i = 0; i < top; ++i) {
2126 field = &klass->fields [i];
2127 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
2128 klass->fields [i].offset = field_offsets [i];
2131 mono_memory_barrier ();
2132 klass->size_inited = 1;
2133 mono_loader_unlock ();
2136 * Compute static field layout and size
2137 * Static fields can reference the class itself, so this has to be
2138 * done after instance_size etc. are initialized.
2141 for (i = 0; i < top; i++) {
2145 field = &klass->fields [i];
2147 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2149 if (mono_field_is_deleted (field))
2152 if (mono_type_has_exceptions (field->type)) {
2153 mono_class_set_type_load_failure (klass, "Field '%s' has an invalid type.", field->name);
2157 has_static_fields = TRUE;
2159 size = mono_type_size (field->type, &align);
2160 field_offsets [i] = class_size;
2161 /*align is always non-zero here*/
2162 field_offsets [i] += align - 1;
2163 field_offsets [i] &= ~(align - 1);
2164 class_size = field_offsets [i] + size;
2167 if (has_static_fields && class_size == 0)
2168 /* Simplify code which depends on class_size != 0 if the class has static fields */
2171 /* Compute klass->has_static_refs */
2172 has_static_refs = FALSE;
2173 for (i = 0; i < top; i++) {
2176 field = &klass->fields [i];
2178 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
2179 ftype = mono_type_get_underlying_type (field->type);
2180 ftype = mono_type_get_basic_type_from_generic (ftype);
2181 if (type_has_references (klass, ftype))
2182 has_static_refs = TRUE;
2186 /*valuetypes can't be neither bigger than 1Mb or empty. */
2187 if (klass->valuetype && (klass->instance_size <= 0 || klass->instance_size > (0x100000 + sizeof (MonoObject))))
2188 mono_class_set_type_load_failure (klass, "Value type instance size (%d) cannot be zero, negative, or bigger than 1Mb", klass->instance_size);
2190 /* Publish the data */
2191 mono_loader_lock ();
2193 klass->sizes.class_size = class_size;
2194 klass->has_static_refs = has_static_refs;
2195 for (i = 0; i < top; ++i) {
2196 field = &klass->fields [i];
2198 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2199 field->offset = field_offsets [i];
2202 mono_memory_barrier ();
2203 klass->fields_inited = 1;
2204 mono_loader_unlock ();
2206 g_free (field_offsets);
2207 g_free (fields_has_references);
2211 create_array_method (MonoClass *klass, const char *name, MonoMethodSignature *sig)
2215 method = (MonoMethod *) mono_image_alloc0 (klass->image, sizeof (MonoMethodPInvoke));
2216 method->klass = klass;
2217 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2218 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2219 method->signature = sig;
2220 method->name = name;
2223 if (name [0] == '.') {
2224 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2226 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2232 * mono_class_setup_methods:
2235 * Initializes the 'methods' array in CLASS.
2236 * Calling this method should be avoided if possible since it allocates a lot
2237 * of long-living MonoMethod structures.
2238 * Methods belonging to an interface are assigned a sequential slot starting
2241 * On failure this function sets klass->has_failure and stores a MonoErrorBoxed with details
2244 mono_class_setup_methods (MonoClass *klass)
2247 MonoMethod **methods;
2252 if (mono_class_is_ginst (klass)) {
2254 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2256 mono_class_init (gklass);
2257 if (!mono_class_has_failure (gklass))
2258 mono_class_setup_methods (gklass);
2259 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2262 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2263 count = mono_class_get_method_count (gklass);
2264 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * (count + 1));
2266 for (i = 0; i < count; i++) {
2267 methods [i] = mono_class_inflate_generic_method_full_checked (
2268 gklass->methods [i], klass, mono_class_get_context (klass), &error);
2269 if (!mono_error_ok (&error)) {
2270 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2271 mono_class_set_type_load_failure (klass, "Could not inflate method %s due to %s", method, mono_error_get_message (&error));
2274 mono_error_cleanup (&error);
2278 } else if (klass->rank) {
2280 MonoMethod *amethod;
2281 MonoMethodSignature *sig;
2282 int count_generic = 0, first_generic = 0;
2284 gboolean jagged_ctor = FALSE;
2286 count = 3 + (klass->rank > 1? 2: 1);
2288 mono_class_setup_interfaces (klass, &error);
2289 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2291 if (klass->rank == 1 && klass->element_class->rank) {
2296 if (klass->interface_count) {
2297 count_generic = generic_array_methods (klass);
2298 first_generic = count;
2299 count += klass->interface_count * count_generic;
2302 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * count);
2304 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2305 sig->ret = &mono_defaults.void_class->byval_arg;
2306 sig->pinvoke = TRUE;
2307 sig->hasthis = TRUE;
2308 for (i = 0; i < klass->rank; ++i)
2309 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2311 amethod = create_array_method (klass, ".ctor", sig);
2312 methods [method_num++] = amethod;
2313 if (klass->rank > 1) {
2314 sig = mono_metadata_signature_alloc (klass->image, klass->rank * 2);
2315 sig->ret = &mono_defaults.void_class->byval_arg;
2316 sig->pinvoke = TRUE;
2317 sig->hasthis = TRUE;
2318 for (i = 0; i < klass->rank * 2; ++i)
2319 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2321 amethod = create_array_method (klass, ".ctor", sig);
2322 methods [method_num++] = amethod;
2326 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2327 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2328 sig->ret = &mono_defaults.void_class->byval_arg;
2329 sig->pinvoke = TRUE;
2330 sig->hasthis = TRUE;
2331 for (i = 0; i < klass->rank + 1; ++i)
2332 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2333 amethod = create_array_method (klass, ".ctor", sig);
2334 methods [method_num++] = amethod;
2337 /* element Get (idx11, [idx2, ...]) */
2338 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2339 sig->ret = &klass->element_class->byval_arg;
2340 sig->pinvoke = TRUE;
2341 sig->hasthis = TRUE;
2342 for (i = 0; i < klass->rank; ++i)
2343 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2344 amethod = create_array_method (klass, "Get", sig);
2345 methods [method_num++] = amethod;
2346 /* element& Address (idx11, [idx2, ...]) */
2347 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2348 sig->ret = &klass->element_class->this_arg;
2349 sig->pinvoke = TRUE;
2350 sig->hasthis = TRUE;
2351 for (i = 0; i < klass->rank; ++i)
2352 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2353 amethod = create_array_method (klass, "Address", sig);
2354 methods [method_num++] = amethod;
2355 /* void Set (idx11, [idx2, ...], element) */
2356 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2357 sig->ret = &mono_defaults.void_class->byval_arg;
2358 sig->pinvoke = TRUE;
2359 sig->hasthis = TRUE;
2360 for (i = 0; i < klass->rank; ++i)
2361 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2362 sig->params [i] = &klass->element_class->byval_arg;
2363 amethod = create_array_method (klass, "Set", sig);
2364 methods [method_num++] = amethod;
2366 for (i = 0; i < klass->interface_count; i++)
2367 setup_generic_array_ifaces (klass, klass->interfaces [i], methods, first_generic + i * count_generic);
2368 } else if (mono_class_has_static_metadata (klass)) {
2370 int first_idx = mono_class_get_first_method_idx (klass);
2372 count = mono_class_get_method_count (klass);
2373 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * count);
2374 for (i = 0; i < count; ++i) {
2375 int idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_METHOD, first_idx + i + 1);
2376 methods [i] = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | idx, klass, NULL, &error);
2378 mono_class_set_type_load_failure (klass, "Could not load method %d due to %s", i, mono_error_get_message (&error));
2379 mono_error_cleanup (&error);
2383 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * 1);
2387 if (MONO_CLASS_IS_INTERFACE (klass)) {
2389 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2390 for (i = 0; i < count; ++i) {
2391 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2392 methods [i]->slot = slot++;
2396 mono_image_lock (klass->image);
2398 if (!klass->methods) {
2399 mono_class_set_method_count (klass, count);
2401 /* Needed because of the double-checking locking pattern */
2402 mono_memory_barrier ();
2404 klass->methods = methods;
2407 mono_image_unlock (klass->image);
2411 * mono_class_get_method_by_index:
2413 * Returns klass->methods [index], initializing klass->methods if neccesary.
2415 * LOCKING: Acquires the loader lock.
2418 mono_class_get_method_by_index (MonoClass *klass, int index)
2422 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
2423 /* Avoid calling setup_methods () if possible */
2424 if (gklass && !klass->methods) {
2427 m = mono_class_inflate_generic_method_full_checked (
2428 gklass->container_class->methods [index], klass, mono_class_get_context (klass), &error);
2429 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2431 * If setup_methods () is called later for this class, no duplicates are created,
2432 * since inflate_generic_method guarantees that only one instance of a method
2433 * is created for each context.
2436 mono_class_setup_methods (klass);
2437 g_assert (m == klass->methods [index]);
2441 mono_class_setup_methods (klass);
2442 if (mono_class_has_failure (klass)) /*FIXME do proper error handling*/
2444 g_assert (index >= 0 && index < mono_class_get_method_count (klass));
2445 return klass->methods [index];
2450 * mono_class_get_inflated_method:
2452 * Given an inflated class CLASS and a method METHOD which should be a method of
2453 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2456 mono_class_get_inflated_method (MonoClass *klass, MonoMethod *method)
2458 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2461 g_assert (method->klass == gklass);
2463 mono_class_setup_methods (gklass);
2464 g_assert (!mono_class_has_failure (gklass)); /*FIXME do proper error handling*/
2466 mcount = mono_class_get_method_count (gklass);
2467 for (i = 0; i < mcount; ++i) {
2468 if (gklass->methods [i] == method) {
2469 if (klass->methods) {
2470 return klass->methods [i];
2473 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], klass, mono_class_get_context (klass), &error);
2474 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2484 * mono_class_get_vtable_entry:
2486 * Returns klass->vtable [offset], computing it if neccesary. Returns NULL on failure.
2487 * LOCKING: Acquires the loader lock.
2490 mono_class_get_vtable_entry (MonoClass *klass, int offset)
2494 if (klass->rank == 1) {
2496 * szarrays do not overwrite any methods of Array, so we can avoid
2497 * initializing their vtables in some cases.
2499 mono_class_setup_vtable (klass->parent);
2500 if (offset < klass->parent->vtable_size)
2501 return klass->parent->vtable [offset];
2504 if (mono_class_is_ginst (klass)) {
2506 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2507 mono_class_setup_vtable (gklass);
2508 m = gklass->vtable [offset];
2510 m = mono_class_inflate_generic_method_full_checked (m, klass, mono_class_get_context (klass), &error);
2511 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2513 mono_class_setup_vtable (klass);
2514 if (mono_class_has_failure (klass))
2516 m = klass->vtable [offset];
2523 * mono_class_get_vtable_size:
2525 * Return the vtable size for KLASS.
2528 mono_class_get_vtable_size (MonoClass *klass)
2530 mono_class_setup_vtable (klass);
2532 return klass->vtable_size;
2536 * mono_class_setup_properties:
2538 * Initialize klass->ext.property and klass->ext.properties.
2540 * This method can fail the class.
2543 mono_class_setup_properties (MonoClass *klass)
2545 guint startm, endm, i, j;
2546 guint32 cols [MONO_PROPERTY_SIZE];
2547 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2548 MonoProperty *properties;
2552 MonoClassExt *ext = mono_class_get_ext (klass);
2553 if (ext && ext->properties)
2556 if (mono_class_is_ginst (klass)) {
2557 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2559 mono_class_init (gklass);
2560 mono_class_setup_properties (gklass);
2561 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2564 MonoClassExt *gext = mono_class_get_ext (gklass);
2565 properties = mono_class_new0 (klass, MonoProperty, gext->property.count + 1);
2567 for (i = 0; i < gext->property.count; i++) {
2569 MonoProperty *prop = &properties [i];
2571 *prop = gext->properties [i];
2574 prop->get = mono_class_inflate_generic_method_full_checked (
2575 prop->get, klass, mono_class_get_context (klass), &error);
2577 prop->set = mono_class_inflate_generic_method_full_checked (
2578 prop->set, klass, mono_class_get_context (klass), &error);
2580 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2581 prop->parent = klass;
2584 first = gext->property.first;
2585 count = gext->property.count;
2587 first = mono_metadata_properties_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2588 count = last - first;
2591 mono_class_setup_methods (klass);
2592 if (mono_class_has_failure (klass))
2596 properties = (MonoProperty *)mono_class_alloc0 (klass, sizeof (MonoProperty) * count);
2597 for (i = first; i < last; ++i) {
2598 mono_metadata_decode_table_row (klass->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2599 properties [i - first].parent = klass;
2600 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2601 properties [i - first].name = mono_metadata_string_heap (klass->image, cols [MONO_PROPERTY_NAME]);
2603 startm = mono_metadata_methods_from_property (klass->image, i, &endm);
2604 int first_idx = mono_class_get_first_method_idx (klass);
2605 for (j = startm; j < endm; ++j) {
2608 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2610 if (klass->image->uncompressed_metadata) {
2612 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2613 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2614 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2616 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - first_idx];
2619 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2620 case METHOD_SEMANTIC_SETTER:
2621 properties [i - first].set = method;
2623 case METHOD_SEMANTIC_GETTER:
2624 properties [i - first].get = method;
2633 mono_class_alloc_ext (klass);
2634 ext = mono_class_get_ext (klass);
2636 mono_image_lock (klass->image);
2638 if (ext->properties) {
2639 /* We leak 'properties' which was allocated from the image mempool */
2640 mono_image_unlock (klass->image);
2644 ext->property.first = first;
2645 ext->property.count = count;
2647 /* Flush any pending writes as we do double checked locking on klass->ext->properties */
2648 mono_memory_barrier ();
2650 /* Leave this assignment as the last op in the function */
2651 ext->properties = properties;
2653 mono_image_unlock (klass->image);
2657 inflate_method_listz (MonoMethod **methods, MonoClass *klass, MonoGenericContext *context)
2659 MonoMethod **om, **retval;
2662 for (om = methods, count = 0; *om; ++om, ++count)
2665 retval = g_new0 (MonoMethod*, count + 1);
2667 for (om = methods, count = 0; *om; ++om, ++count) {
2669 retval [count] = mono_class_inflate_generic_method_full_checked (*om, klass, context, &error);
2670 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2676 /*This method can fail the class.*/
2678 mono_class_setup_events (MonoClass *klass)
2681 guint startm, endm, i, j;
2682 guint32 cols [MONO_EVENT_SIZE];
2683 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2687 MonoClassExt *ext = mono_class_get_ext (klass);
2688 if (ext && ext->events)
2691 if (mono_class_is_ginst (klass)) {
2692 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2693 MonoGenericContext *context = NULL;
2695 mono_class_setup_events (gklass);
2696 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2699 MonoClassExt *gext = mono_class_get_ext (gklass);
2700 first = gext->event.first;
2701 count = gext->event.count;
2703 events = mono_class_new0 (klass, MonoEvent, count);
2706 context = mono_class_get_context (klass);
2708 for (i = 0; i < count; i++) {
2710 MonoEvent *event = &events [i];
2711 MonoEvent *gevent = &gext->events [i];
2713 mono_error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2715 event->parent = klass;
2716 event->name = gevent->name;
2717 event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, klass, context, &error) : NULL;
2718 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2719 event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, klass, context, &error) : NULL;
2720 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2721 event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, klass, context, &error) : NULL;
2722 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2724 #ifndef MONO_SMALL_CONFIG
2725 event->other = gevent->other ? inflate_method_listz (gevent->other, klass, context) : NULL;
2727 event->attrs = gevent->attrs;
2730 first = mono_metadata_events_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2731 count = last - first;
2734 mono_class_setup_methods (klass);
2735 if (mono_class_has_failure (klass)) {
2740 events = (MonoEvent *)mono_class_alloc0 (klass, sizeof (MonoEvent) * count);
2741 for (i = first; i < last; ++i) {
2742 MonoEvent *event = &events [i - first];
2744 mono_metadata_decode_table_row (klass->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2745 event->parent = klass;
2746 event->attrs = cols [MONO_EVENT_FLAGS];
2747 event->name = mono_metadata_string_heap (klass->image, cols [MONO_EVENT_NAME]);
2749 startm = mono_metadata_methods_from_event (klass->image, i, &endm);
2750 int first_idx = mono_class_get_first_method_idx (klass);
2751 for (j = startm; j < endm; ++j) {
2754 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2756 if (klass->image->uncompressed_metadata) {
2758 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2759 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2760 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2762 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - first_idx];
2765 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2766 case METHOD_SEMANTIC_ADD_ON:
2767 event->add = method;
2769 case METHOD_SEMANTIC_REMOVE_ON:
2770 event->remove = method;
2772 case METHOD_SEMANTIC_FIRE:
2773 event->raise = method;
2775 case METHOD_SEMANTIC_OTHER: {
2776 #ifndef MONO_SMALL_CONFIG
2779 if (event->other == NULL) {
2780 event->other = g_new0 (MonoMethod*, 2);
2782 while (event->other [n])
2784 event->other = (MonoMethod **)g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2786 event->other [n] = method;
2787 /* NULL terminated */
2788 event->other [n + 1] = NULL;
2799 mono_class_alloc_ext (klass);
2800 ext = mono_class_get_ext (klass);
2802 mono_image_lock (klass->image);
2805 mono_image_unlock (klass->image);
2809 ext->event.first = first;
2810 ext->event.count = count;
2812 /* Flush any pending writes as we do double checked locking on klass->ext.events */
2813 mono_memory_barrier ();
2815 /* Leave this assignment as the last op in the function */
2816 ext->events = events;
2818 mono_image_unlock (klass->image);
2822 * Global pool of interface IDs, represented as a bitset.
2823 * LOCKING: Protected by the classes lock.
2825 static MonoBitSet *global_interface_bitset = NULL;
2828 * mono_unload_interface_ids:
2829 * @bitset: bit set of interface IDs
2831 * When an image is unloaded, the interface IDs associated with
2832 * the image are put back in the global pool of IDs so the numbers
2836 mono_unload_interface_ids (MonoBitSet *bitset)
2839 mono_bitset_sub (global_interface_bitset, bitset);
2844 mono_unload_interface_id (MonoClass *klass)
2846 if (global_interface_bitset && klass->interface_id) {
2848 mono_bitset_clear (global_interface_bitset, klass->interface_id);
2854 * mono_get_unique_iid:
2857 * Assign a unique integer ID to the interface represented by @class.
2858 * The ID will positive and as small as possible.
2859 * LOCKING: Acquires the classes lock.
2860 * Returns: The new ID.
2863 mono_get_unique_iid (MonoClass *klass)
2867 g_assert (MONO_CLASS_IS_INTERFACE (klass));
2871 if (!global_interface_bitset) {
2872 global_interface_bitset = mono_bitset_new (128, 0);
2875 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2877 int old_size = mono_bitset_size (global_interface_bitset);
2878 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2879 mono_bitset_free (global_interface_bitset);
2880 global_interface_bitset = new_set;
2883 mono_bitset_set (global_interface_bitset, iid);
2884 /* set the bit also in the per-image set */
2885 if (!mono_class_is_ginst (klass)) {
2886 if (klass->image->interface_bitset) {
2887 if (iid >= mono_bitset_size (klass->image->interface_bitset)) {
2888 MonoBitSet *new_set = mono_bitset_clone (klass->image->interface_bitset, iid + 1);
2889 mono_bitset_free (klass->image->interface_bitset);
2890 klass->image->interface_bitset = new_set;
2893 klass->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2895 mono_bitset_set (klass->image->interface_bitset, iid);
2900 #ifndef MONO_SMALL_CONFIG
2901 if (mono_print_vtable) {
2903 char *type_name = mono_type_full_name (&klass->byval_arg);
2904 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
2905 if (gklass && !gklass->context.class_inst->is_open) {
2906 generic_id = gklass->context.class_inst->id;
2907 g_assert (generic_id != 0);
2911 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, klass->image->name, type_name, generic_id);
2916 /* I've confirmed iids safe past 16 bits, however bitset code uses a signed int while testing.
2917 * Once this changes, it should be safe for us to allow 2^32-1 interfaces, until then 2^31-2 is the max. */
2918 g_assert (iid < INT_MAX);
2923 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, GHashTable **ifaces, MonoError *error)
2928 mono_class_setup_interfaces (klass, error);
2929 return_if_nok (error);
2931 for (i = 0; i < klass->interface_count; i++) {
2932 ic = klass->interfaces [i];
2935 *res = g_ptr_array_new ();
2936 if (*ifaces == NULL)
2937 *ifaces = g_hash_table_new (NULL, NULL);
2938 if (g_hash_table_lookup (*ifaces, ic))
2940 g_ptr_array_add (*res, ic);
2941 g_hash_table_insert (*ifaces, ic, ic);
2942 mono_class_init (ic);
2943 if (mono_class_has_failure (ic)) {
2944 mono_error_set_type_load_class (error, ic, "Error Loading class");
2948 collect_implemented_interfaces_aux (ic, res, ifaces, error);
2949 return_if_nok (error);
2954 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2956 GPtrArray *res = NULL;
2957 GHashTable *ifaces = NULL;
2959 collect_implemented_interfaces_aux (klass, &res, &ifaces, error);
2961 g_hash_table_destroy (ifaces);
2962 if (!mono_error_ok (error)) {
2964 g_ptr_array_free (res, TRUE);
2971 compare_interface_ids (const void *p_key, const void *p_element)
2973 const MonoClass *key = (const MonoClass *)p_key;
2974 const MonoClass *element = *(const MonoClass **)p_element;
2976 return (key->interface_id - element->interface_id);
2979 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2981 mono_class_interface_offset (MonoClass *klass, MonoClass *itf)
2983 MonoClass **result = (MonoClass **)mono_binary_search (
2985 klass->interfaces_packed,
2986 klass->interface_offsets_count,
2987 sizeof (MonoClass *),
2988 compare_interface_ids);
2990 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2997 * mono_class_interface_offset_with_variance:
2999 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
3000 * If @itf is an interface with generic variant arguments, try to find the compatible one.
3002 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
3004 * FIXME figure out MS disambiguation rules and fix this function.
3007 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match)
3009 int i = mono_class_interface_offset (klass, itf);
3010 *non_exact_match = FALSE;
3014 if (!mono_class_has_variant_generic_params (itf))
3017 for (i = 0; i < klass->interface_offsets_count; i++) {
3018 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
3019 *non_exact_match = TRUE;
3020 return klass->interface_offsets_packed [i];
3028 print_implemented_interfaces (MonoClass *klass)
3032 GPtrArray *ifaces = NULL;
3034 int ancestor_level = 0;
3036 name = mono_type_get_full_name (klass);
3037 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
3040 for (i = 0; i < klass->interface_offsets_count; i++)
3041 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3042 klass->interfaces_packed [i]->interface_id,
3043 klass->interface_offsets_packed [i],
3044 mono_class_get_method_count (klass->interfaces_packed [i]),
3045 klass->interfaces_packed [i]->name_space,
3046 klass->interfaces_packed [i]->name );
3047 printf ("Interface flags: ");
3048 for (i = 0; i <= klass->max_interface_id; i++)
3049 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
3050 printf ("(%d,T)", i);
3052 printf ("(%d,F)", i);
3054 printf ("Dump interface flags:");
3055 #ifdef COMPRESSED_INTERFACE_BITMAP
3057 const uint8_t* p = klass->interface_bitmap;
3058 i = klass->max_interface_id;
3060 printf (" %d x 00 %02X", p [0], p [1]);
3066 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
3067 printf (" %02X", klass->interface_bitmap [i]);
3070 while (klass != NULL) {
3071 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
3072 ifaces = mono_class_get_implemented_interfaces (klass, &error);
3073 if (!mono_error_ok (&error)) {
3074 printf (" Type failed due to %s\n", mono_error_get_message (&error));
3075 mono_error_cleanup (&error);
3076 } else if (ifaces) {
3077 for (i = 0; i < ifaces->len; i++) {
3078 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3079 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
3080 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3082 mono_class_interface_offset (klass, ic),
3083 mono_class_get_method_count (ic),
3087 g_ptr_array_free (ifaces, TRUE);
3090 klass = klass->parent;
3095 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
3098 args [0] = &arg0->byval_arg;
3100 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
3104 array_class_get_if_rank (MonoClass *klass, guint rank)
3106 return rank ? mono_array_class_get (klass, rank) : klass;
3110 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
3112 valuetype_types [0] = eclass;
3113 if (eclass == mono_defaults.int16_class)
3114 valuetype_types [1] = mono_defaults.uint16_class;
3115 else if (eclass == mono_defaults.uint16_class)
3116 valuetype_types [1] = mono_defaults.int16_class;
3117 else if (eclass == mono_defaults.int32_class)
3118 valuetype_types [1] = mono_defaults.uint32_class;
3119 else if (eclass == mono_defaults.uint32_class)
3120 valuetype_types [1] = mono_defaults.int32_class;
3121 else if (eclass == mono_defaults.int64_class)
3122 valuetype_types [1] = mono_defaults.uint64_class;
3123 else if (eclass == mono_defaults.uint64_class)
3124 valuetype_types [1] = mono_defaults.int64_class;
3125 else if (eclass == mono_defaults.byte_class)
3126 valuetype_types [1] = mono_defaults.sbyte_class;
3127 else if (eclass == mono_defaults.sbyte_class)
3128 valuetype_types [1] = mono_defaults.byte_class;
3129 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
3130 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
3133 static GENERATE_GET_CLASS_WITH_CACHE (generic_icollection, System.Collections.Generic, ICollection`1)
3134 static GENERATE_GET_CLASS_WITH_CACHE (generic_ienumerable, System.Collections.Generic, IEnumerable`1)
3135 static GENERATE_GET_CLASS_WITH_CACHE (generic_ienumerator, System.Collections.Generic, IEnumerator`1)
3136 static GENERATE_GET_CLASS_WITH_CACHE (generic_ireadonlylist, System.Collections.Generic, IReadOnlyList`1)
3137 static GENERATE_GET_CLASS_WITH_CACHE (generic_ireadonlycollection, System.Collections.Generic, IReadOnlyCollection`1)
3139 /* this won't be needed once bug #325495 is completely fixed
3140 * though we'll need something similar to know which interfaces to allow
3141 * in arrays when they'll be lazyly created
3143 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
3144 * MS returns diferrent types based on which instance is called. For example:
3145 * object obj = new byte[10][];
3146 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
3147 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
3150 * Fixing this should kill quite some code, save some bits and improve compatibility.
3153 get_implicit_generic_array_interfaces (MonoClass *klass, int *num, int *is_enumerator)
3155 MonoClass *eclass = klass->element_class;
3156 MonoClass* generic_icollection_class;
3157 MonoClass* generic_ienumerable_class;
3158 MonoClass* generic_ienumerator_class;
3159 MonoClass* generic_ireadonlylist_class;
3160 MonoClass* generic_ireadonlycollection_class;
3161 MonoClass *valuetype_types[2] = { NULL, NULL };
3162 MonoClass **interfaces = NULL;
3163 int i, nifaces, interface_count, real_count, original_rank;
3165 gboolean internal_enumerator;
3166 gboolean eclass_is_valuetype;
3168 if (!mono_defaults.generic_ilist_class) {
3172 internal_enumerator = FALSE;
3173 eclass_is_valuetype = FALSE;
3174 original_rank = eclass->rank;
3175 if (klass->byval_arg.type != MONO_TYPE_SZARRAY) {
3176 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
3177 if (gklass && klass->nested_in == mono_defaults.array_class && strcmp (klass->name, "InternalEnumerator`1") == 0) {
3179 * For a Enumerator<T[]> we need to get the list of interfaces for T.
3181 eclass = mono_class_from_mono_type (gklass->context.class_inst->type_argv [0]);
3182 original_rank = eclass->rank;
3184 eclass = eclass->element_class;
3185 internal_enumerator = TRUE;
3186 *is_enumerator = TRUE;
3194 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
3195 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
3197 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
3199 generic_icollection_class = mono_class_get_generic_icollection_class ();
3200 generic_ienumerable_class = mono_class_get_generic_ienumerable_class ();
3201 generic_ienumerator_class = mono_class_get_generic_ienumerator_class ();
3202 generic_ireadonlylist_class = mono_class_get_generic_ireadonlylist_class ();
3203 generic_ireadonlycollection_class = mono_class_get_generic_ireadonlycollection_class ();
3205 mono_class_init (eclass);
3208 * Arrays in 2.0 need to implement a number of generic interfaces
3209 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
3210 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
3211 * We collect the types needed to build the
3212 * instantiations in interfaces at intervals of 3/5, because 3/5 are
3213 * the generic interfaces needed to implement.
3215 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
3216 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
3218 if (eclass->valuetype) {
3219 nifaces = generic_ireadonlylist_class ? 5 : 3;
3220 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
3222 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
3223 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
3224 if (internal_enumerator) {
3226 if (valuetype_types [1])
3230 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3231 interfaces [0] = valuetype_types [0];
3232 if (valuetype_types [1])
3233 interfaces [nifaces] = valuetype_types [1];
3235 eclass_is_valuetype = TRUE;
3238 int idepth = eclass->idepth;
3239 if (!internal_enumerator)
3241 nifaces = generic_ireadonlylist_class ? 2 : 3;
3243 // FIXME: This doesn't seem to work/required for generic params
3244 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
3245 mono_class_setup_interface_offsets (eclass);
3247 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
3248 /* we add object for interfaces and the supertypes for the other
3249 * types. The last of the supertypes is the element class itself which we
3250 * already created the explicit interfaces for (so we include it for IEnumerator
3251 * and exclude it for arrays).
3253 if (MONO_CLASS_IS_INTERFACE (eclass))
3256 interface_count += idepth;
3257 if (eclass->rank && eclass->element_class->valuetype) {
3258 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3259 if (valuetype_types [1])
3262 /* IList, ICollection, IEnumerable, IReadOnlyList */
3263 interface_count *= nifaces;
3264 real_count = interface_count;
3265 if (internal_enumerator) {
3266 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3267 if (valuetype_types [1])
3270 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3271 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3272 interfaces [0] = mono_defaults.object_class;
3276 for (i = 0; i < idepth; i++) {
3277 mono_class_init (eclass->supertypes [i]);
3278 interfaces [j] = eclass->supertypes [i];
3282 if (all_interfaces) {
3283 for (i = 0; i < eclass->interface_offsets_count; i++) {
3284 interfaces [j] = eclass->interfaces_packed [i];
3288 for (i = 0; i < eclass->interface_count; i++) {
3289 interfaces [j] = eclass->interfaces [i];
3293 if (valuetype_types [1]) {
3294 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3299 /* instantiate the generic interfaces */
3300 for (i = 0; i < interface_count; i += nifaces) {
3301 MonoClass *iface = interfaces [i];
3303 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3304 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3306 if (eclass->valuetype) {
3307 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3308 if (generic_ireadonlylist_class) {
3309 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3310 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3313 if (!generic_ireadonlylist_class)
3314 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3317 if (internal_enumerator) {
3319 /* instantiate IEnumerator<iface> */
3320 for (i = 0; i < interface_count; i++) {
3321 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3323 j = interface_count;
3324 if (!eclass_is_valuetype) {
3325 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3326 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3329 for (i = 0; i < eclass->idepth; i++) {
3330 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3334 for (i = 0; i < eclass->interface_offsets_count; i++) {
3335 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3339 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3341 if (valuetype_types [1])
3342 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3346 char *type_name = mono_type_get_name_full (&klass->byval_arg, 0);
3347 for (i = 0; i < real_count; ++i) {
3348 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3349 g_print ("%s implements %s\n", type_name, name);
3360 find_array_interface (MonoClass *klass, const char *name)
3363 for (i = 0; i < klass->interface_count; ++i) {
3364 if (strcmp (klass->interfaces [i]->name, name) == 0)
3371 * Return the number of virtual methods.
3372 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3373 * Return -1 on failure.
3374 * FIXME It would be nice if this information could be cached somewhere.
3377 count_virtual_methods (MonoClass *klass)
3379 int i, mcount, vcount = 0;
3381 klass = mono_class_get_generic_type_definition (klass); /*We can find this information by looking at the GTD*/
3383 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
3384 mono_class_setup_methods (klass);
3385 if (mono_class_has_failure (klass))
3388 mcount = mono_class_get_method_count (klass);
3389 for (i = 0; i < mcount; ++i) {
3390 flags = klass->methods [i]->flags;
3391 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3395 int first_idx = mono_class_get_first_method_idx (klass);
3396 mcount = mono_class_get_method_count (klass);
3397 for (i = 0; i < mcount; ++i) {
3398 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
3400 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3408 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3416 m = (l + num_ifaces) / 2;
3417 if (interfaces_full [m] == ic)
3419 if (l == num_ifaces)
3421 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3430 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3432 int i = find_interface (num_ifaces, interfaces_full, ic);
3434 return interface_offsets_full [i];
3439 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3441 int i = find_interface (num_ifaces, interfaces_full, ic);
3445 interface_offsets_full [i] = offset;
3448 for (i = 0; i < num_ifaces; ++i) {
3449 if (interfaces_full [i]) {
3451 if (interfaces_full [i]->interface_id < ic->interface_id)
3454 while (end < num_ifaces && interfaces_full [end]) end++;
3455 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3456 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3458 interfaces_full [i] = ic;
3459 interface_offsets_full [i] = offset;
3465 #ifdef COMPRESSED_INTERFACE_BITMAP
3468 * Compressed interface bitmap design.
3470 * Interface bitmaps take a large amount of memory, because their size is
3471 * linear with the maximum interface id assigned in the process (each interface
3472 * is assigned a unique id as it is loaded). The number of interface classes
3473 * is high because of the many implicit interfaces implemented by arrays (we'll
3474 * need to lazy-load them in the future).
3475 * Most classes implement a very small number of interfaces, so the bitmap is
3476 * sparse. This bitmap needs to be checked by interface casts, so access to the
3477 * needed bit must be fast and doable with few jit instructions.
3479 * The current compression format is as follows:
3480 * *) it is a sequence of one or more two-byte elements
3481 * *) the first byte in the element is the count of empty bitmap bytes
3482 * at the current bitmap position
3483 * *) the second byte in the element is an actual bitmap byte at the current
3486 * As an example, the following compressed bitmap bytes:
3487 * 0x07 0x01 0x00 0x7
3488 * correspond to the following bitmap:
3489 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3491 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3492 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3493 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3497 * mono_compress_bitmap:
3498 * @dest: destination buffer
3499 * @bitmap: bitmap buffer
3500 * @size: size of @bitmap in bytes
3502 * This is a mono internal function.
3503 * The @bitmap data is compressed into a format that is small but
3504 * still searchable in few instructions by the JIT and runtime.
3505 * The compressed data is stored in the buffer pointed to by the
3506 * @dest array. Passing a #NULL value for @dest allows to just compute
3507 * the size of the buffer.
3508 * This compression algorithm assumes the bits set in the bitmap are
3509 * few and far between, like in interface bitmaps.
3510 * Returns: The size of the compressed bitmap in bytes.
3513 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3517 const uint8_t *end = bitmap + size;
3518 while (bitmap < end) {
3519 if (*bitmap || numz == 255) {
3543 * mono_class_interface_match:
3544 * @bitmap: a compressed bitmap buffer
3545 * @id: the index to check in the bitmap
3547 * This is a mono internal function.
3548 * Checks if a bit is set in a compressed interface bitmap. @id must
3549 * be already checked for being smaller than the maximum id encoded in the
3552 * Returns: A non-zero value if bit @id is set in the bitmap @bitmap,
3556 mono_class_interface_match (const uint8_t *bitmap, int id)
3559 id -= bitmap [0] * 8;
3563 return bitmap [1] & (1 << id);
3572 * Return -1 on failure and set klass->has_failure and store a MonoErrorBoxed with the details.
3573 * LOCKING: Acquires the loader lock.
3576 setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite)
3580 int i, j, num_ifaces;
3582 MonoClass **interfaces_full = NULL;
3583 int *interface_offsets_full = NULL;
3585 GPtrArray **ifaces_array = NULL;
3586 int interface_offsets_count;
3587 MonoClass **array_interfaces = NULL;
3588 int num_array_interfaces;
3589 int is_enumerator = FALSE;
3591 mono_loader_lock ();
3593 mono_class_setup_supertypes (klass);
3595 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3596 * implicit interfaces have the property that they are assigned the same slot in the
3597 * vtables for compatible interfaces
3599 array_interfaces = get_implicit_generic_array_interfaces (klass, &num_array_interfaces, &is_enumerator);
3601 /* compute maximum number of slots and maximum interface id */
3603 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3604 ifaces_array = g_new0 (GPtrArray *, klass->idepth);
3605 for (j = 0; j < klass->idepth; j++) {
3606 k = klass->supertypes [j];
3608 num_ifaces += k->interface_count;
3609 for (i = 0; i < k->interface_count; i++) {
3610 ic = k->interfaces [i];
3612 mono_class_init (ic);
3614 if (max_iid < ic->interface_id)
3615 max_iid = ic->interface_id;
3617 ifaces = mono_class_get_implemented_interfaces (k, &error);
3618 if (!mono_error_ok (&error)) {
3619 char *name = mono_type_get_full_name (k);
3620 mono_class_set_type_load_failure (klass, "Error getting the interfaces of %s due to %s", name, mono_error_get_message (&error));
3622 mono_error_cleanup (&error);
3627 num_ifaces += ifaces->len;
3628 for (i = 0; i < ifaces->len; ++i) {
3629 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3630 if (max_iid < ic->interface_id)
3631 max_iid = ic->interface_id;
3633 ifaces_array [j] = ifaces;
3637 for (i = 0; i < num_array_interfaces; ++i) {
3638 ic = array_interfaces [i];
3639 mono_class_init (ic);
3640 if (max_iid < ic->interface_id)
3641 max_iid = ic->interface_id;
3644 if (MONO_CLASS_IS_INTERFACE (klass)) {
3646 if (max_iid < klass->interface_id)
3647 max_iid = klass->interface_id;
3650 /* compute vtable offset for interfaces */
3651 interfaces_full = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3652 interface_offsets_full = (int *)g_malloc (sizeof (int) * num_ifaces);
3654 for (i = 0; i < num_ifaces; i++)
3655 interface_offsets_full [i] = -1;
3657 /* skip the current class */
3658 for (j = 0; j < klass->idepth - 1; j++) {
3659 k = klass->supertypes [j];
3660 ifaces = ifaces_array [j];
3663 for (i = 0; i < ifaces->len; ++i) {
3665 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3667 /*Force the sharing of interface offsets between parent and subtypes.*/
3668 io = mono_class_interface_offset (k, ic);
3670 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3675 g_assert (klass == klass->supertypes [klass->idepth - 1]);
3676 ifaces = ifaces_array [klass->idepth - 1];
3678 for (i = 0; i < ifaces->len; ++i) {
3680 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3681 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3683 count = count_virtual_methods (ic);
3685 char *name = mono_type_get_full_name (ic);
3686 mono_class_set_type_load_failure (klass, "Error calculating interface offset of %s", name);
3695 if (MONO_CLASS_IS_INTERFACE (klass))
3696 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, klass, cur_slot, TRUE);
3698 if (num_array_interfaces) {
3699 if (is_enumerator) {
3700 int ienumerator_idx = find_array_interface (klass, "IEnumerator`1");
3701 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ienumerator_idx]);
3702 g_assert (ienumerator_offset >= 0);
3703 for (i = 0; i < num_array_interfaces; ++i) {
3704 ic = array_interfaces [i];
3705 if (strcmp (ic->name, "IEnumerator`1") == 0)
3706 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3708 g_assert_not_reached ();
3709 /*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);*/
3712 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3713 int ilist_iface_idx = find_array_interface (klass, "IList`1");
3714 MonoClass* ilist_class = klass->interfaces [ilist_iface_idx];
3715 int ireadonlylist_iface_idx = find_array_interface (klass, "IReadOnlyList`1");
3716 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? klass->interfaces [ireadonlylist_iface_idx] : NULL;
3717 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3718 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3719 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3720 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ilist_iface_idx]);
3721 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3722 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3723 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ireadonlylist_iface_idx]) : -1;
3724 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3725 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3726 for (i = 0; i < num_array_interfaces; ++i) {
3728 ic = array_interfaces [i];
3729 if (mono_class_get_generic_class (ic)->container_class == mono_defaults.generic_ilist_class)
3730 offset = ilist_offset;
3731 else if (strcmp (ic->name, "ICollection`1") == 0)
3732 offset = icollection_offset;
3733 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3734 offset = ienumerable_offset;
3735 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3736 offset = ireadonlylist_offset;
3737 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3738 offset = ireadonlycollection_offset;
3740 g_assert_not_reached ();
3741 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3742 /*g_print ("type %s has %s offset at %d (%s)\n", klass->name, ic->name, offset, klass->interfaces [0]->name);*/
3747 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3748 if (interface_offsets_full [i] != -1)
3749 interface_offsets_count ++;
3752 /* Publish the data */
3753 klass->max_interface_id = max_iid;
3755 * We might get called multiple times:
3756 * - mono_class_init ()
3757 * - mono_class_setup_vtable ().
3758 * - mono_class_setup_interface_offsets ().
3759 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3760 * means we have to overwrite those when called from other places (#4440).
3762 if (klass->interfaces_packed) {
3764 g_assert (klass->interface_offsets_count == interface_offsets_count);
3768 klass->interface_offsets_count = interface_offsets_count;
3769 klass->interfaces_packed = (MonoClass **)mono_class_alloc (klass, sizeof (MonoClass*) * interface_offsets_count);
3770 klass->interface_offsets_packed = (guint16 *)mono_class_alloc (klass, sizeof (guint16) * interface_offsets_count);
3771 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3772 #ifdef COMPRESSED_INTERFACE_BITMAP
3773 bitmap = g_malloc0 (bsize);
3775 bitmap = (uint8_t *)mono_class_alloc0 (klass, bsize);
3777 for (i = 0; i < interface_offsets_count; i++) {
3778 guint32 id = interfaces_full [i]->interface_id;
3779 bitmap [id >> 3] |= (1 << (id & 7));
3780 klass->interfaces_packed [i] = interfaces_full [i];
3781 klass->interface_offsets_packed [i] = interface_offsets_full [i];
3782 /*if (num_array_interfaces)
3783 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]);*/
3785 #ifdef COMPRESSED_INTERFACE_BITMAP
3786 i = mono_compress_bitmap (NULL, bitmap, bsize);
3787 klass->interface_bitmap = mono_class_alloc0 (klass, i);
3788 mono_compress_bitmap (klass->interface_bitmap, bitmap, bsize);
3791 klass->interface_bitmap = bitmap;
3795 mono_loader_unlock ();
3797 g_free (interfaces_full);
3798 g_free (interface_offsets_full);
3799 g_free (array_interfaces);
3800 for (i = 0; i < klass->idepth; i++) {
3801 ifaces = ifaces_array [i];
3803 g_ptr_array_free (ifaces, TRUE);
3805 g_free (ifaces_array);
3807 //printf ("JUST DONE: ");
3808 //print_implemented_interfaces (klass);
3814 * Setup interface offsets for interfaces.
3816 * - klass->max_interface_id
3817 * - klass->interface_offsets_count
3818 * - klass->interfaces_packed
3819 * - klass->interface_offsets_packed
3820 * - klass->interface_bitmap
3822 * This function can fail @class.
3825 mono_class_setup_interface_offsets (MonoClass *klass)
3827 setup_interface_offsets (klass, 0, FALSE);
3830 /*Checks if @klass has @parent as one of it's parents type gtd
3834 * Bar<T> : Foo<Bar<Bar<T>>>
3838 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3840 klass = mono_class_get_generic_type_definition (klass);
3841 parent = mono_class_get_generic_type_definition (parent);
3842 mono_class_setup_supertypes (klass);
3843 mono_class_setup_supertypes (parent);
3845 return klass->idepth >= parent->idepth &&
3846 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3850 mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup)
3852 MonoGenericInst *ginst;
3855 if (!mono_class_is_ginst (klass)) {
3856 mono_class_setup_vtable_full (klass, in_setup);
3857 return !mono_class_has_failure (klass);
3860 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup);
3861 if (mono_class_set_type_load_failure_causedby_class (klass, mono_class_get_generic_class (klass)->container_class, "Failed to load generic definition vtable"))
3864 ginst = mono_class_get_generic_class (klass)->context.class_inst;
3865 for (i = 0; i < ginst->type_argc; ++i) {
3867 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3869 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3870 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3871 if (mono_class_has_gtd_parent (klass, arg) || mono_class_has_gtd_parent (arg, klass))
3873 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3874 mono_class_set_type_load_failure (klass, "Failed to load generic parameter %d", i);
3882 * mono_class_setup_vtable:
3884 * Creates the generic vtable of CLASS.
3885 * Initializes the following fields in MonoClass:
3888 * Plus all the fields initialized by setup_interface_offsets ().
3889 * If there is an error during vtable construction, klass->has_failure
3890 * is set and details are stored in a MonoErrorBoxed.
3892 * LOCKING: Acquires the loader lock.
3895 mono_class_setup_vtable (MonoClass *klass)
3897 mono_class_setup_vtable_full (klass, NULL);
3901 mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
3904 MonoMethod **overrides;
3905 MonoGenericContext *context;
3913 if (MONO_CLASS_IS_INTERFACE (klass)) {
3914 /* This sets method->slot for all methods if this is an interface */
3915 mono_class_setup_methods (klass);
3919 if (mono_class_has_failure (klass))
3922 if (g_list_find (in_setup, klass))
3925 mono_loader_lock ();
3927 if (klass->vtable) {
3928 mono_loader_unlock ();
3932 mono_stats.generic_vtable_count ++;
3933 in_setup = g_list_prepend (in_setup, klass);
3935 if (mono_class_is_ginst (klass)) {
3936 if (!mono_class_check_vtable_constraints (klass, in_setup)) {
3937 mono_loader_unlock ();
3938 g_list_remove (in_setup, klass);
3942 context = mono_class_get_context (klass);
3943 type_token = mono_class_get_generic_class (klass)->container_class->type_token;
3945 context = (MonoGenericContext *) mono_class_try_get_generic_container (klass); //FIXME is this a case of a try?
3946 type_token = klass->type_token;
3949 if (image_is_dynamic (klass->image)) {
3950 /* Generic instances can have zero method overrides without causing any harm.
3951 * This is true since we don't do layout all over again for them, we simply inflate
3952 * the layout of the parent.
3954 mono_reflection_get_dynamic_overrides (klass, &overrides, &onum, &error);
3955 if (!is_ok (&error)) {
3956 mono_loader_unlock ();
3957 g_list_remove (in_setup, klass);
3958 mono_class_set_type_load_failure (klass, "Could not load list of method overrides due to %s", mono_error_get_message (&error));
3959 mono_error_cleanup (&error);
3963 /* The following call fails if there are missing methods in the type */
3964 /* FIXME it's probably a good idea to avoid this for generic instances. */
3965 ok = mono_class_get_overrides_full (klass->image, type_token, &overrides, &onum, context);
3969 mono_class_setup_vtable_general (klass, overrides, onum, in_setup);
3971 mono_class_set_type_load_failure (klass, "Could not load list of method overrides");
3975 mono_loader_unlock ();
3976 g_list_remove (in_setup, klass);
3981 #define DEBUG_INTERFACE_VTABLE_CODE 0
3982 #define TRACE_INTERFACE_VTABLE_CODE 0
3983 #define VERIFY_INTERFACE_VTABLE_CODE 0
3984 #define VTABLE_SELECTOR (1)
3986 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3987 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3988 if (!(VTABLE_SELECTOR)) break; \
3992 #define DEBUG_INTERFACE_VTABLE(stmt)
3995 #if TRACE_INTERFACE_VTABLE_CODE
3996 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3997 if (!(VTABLE_SELECTOR)) break; \
4001 #define TRACE_INTERFACE_VTABLE(stmt)
4004 #if VERIFY_INTERFACE_VTABLE_CODE
4005 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
4006 if (!(VTABLE_SELECTOR)) break; \
4010 #define VERIFY_INTERFACE_VTABLE(stmt)
4014 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
4016 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
4020 GString *res = g_string_new ("");
4022 g_string_append_c (res, '(');
4023 for (i = 0; i < sig->param_count; ++i) {
4025 g_string_append_c (res, ',');
4026 mono_type_get_desc (res, sig->params [i], include_namespace);
4028 g_string_append (res, ")=>");
4029 if (sig->ret != NULL) {
4030 mono_type_get_desc (res, sig->ret, include_namespace);
4032 g_string_append (res, "NULL");
4035 g_string_free (res, FALSE);
4039 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
4040 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
4041 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
4042 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
4050 is_wcf_hack_disabled (void)
4052 static gboolean disabled;
4053 static gboolean inited = FALSE;
4055 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
4062 check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
4064 MonoMethodSignature *cmsig, *imsig;
4065 if (strcmp (im->name, cm->name) == 0) {
4066 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
4067 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
4070 if (! slot_is_empty) {
4071 if (require_newslot) {
4072 if (! interface_is_explicitly_implemented_by_class) {
4073 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
4076 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4077 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
4081 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
4084 cmsig = mono_method_signature (cm);
4085 imsig = mono_method_signature (im);
4086 if (!cmsig || !imsig) {
4087 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
4091 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4092 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
4093 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4094 TRACE_INTERFACE_VTABLE (printf ("]"));
4097 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
4098 if (mono_security_core_clr_enabled ())
4099 mono_security_core_clr_check_override (klass, cm, im);
4101 TRACE_INTERFACE_VTABLE (printf ("[NAME 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);
4113 MonoClass *ic = im->klass;
4114 const char *ic_name_space = ic->name_space;
4115 const char *ic_name = ic->name;
4118 if (! require_newslot) {
4119 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
4122 if (cm->klass->rank == 0) {
4123 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
4126 cmsig = mono_method_signature (cm);
4127 imsig = mono_method_signature (im);
4128 if (!cmsig || !imsig) {
4129 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
4133 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4134 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
4135 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4136 TRACE_INTERFACE_VTABLE (printf ("]"));
4139 if (mono_class_get_image (ic) != mono_defaults.corlib) {
4140 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
4143 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
4144 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
4147 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))) {
4148 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
4152 subname = strstr (cm->name, ic_name_space);
4153 if (subname != cm->name) {
4154 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
4157 subname += strlen (ic_name_space);
4158 if (subname [0] != '.') {
4159 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
4163 if (strstr (subname, ic_name) != subname) {
4164 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
4167 subname += strlen (ic_name);
4168 if (subname [0] != '.') {
4169 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
4173 if (strcmp (subname, im->name) != 0) {
4174 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
4178 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
4179 if (mono_security_core_clr_enabled ())
4180 mono_security_core_clr_check_override (klass, cm, im);
4182 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
4183 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4184 char *body_name = mono_method_full_name (cm, TRUE);
4185 char *decl_name = mono_method_full_name (im, TRUE);
4186 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4196 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
4198 foreach_override (gpointer key, gpointer value, gpointer user_data) {
4199 MonoMethod *method = key;
4200 MonoMethod *override = value;
4201 MonoClass *method_class = mono_method_get_class (method);
4202 MonoClass *override_class = mono_method_get_class (override);
4204 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
4205 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
4206 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
4209 print_overrides (GHashTable *override_map, const char *message) {
4211 printf ("Override map \"%s\" START:\n", message);
4212 g_hash_table_foreach (override_map, foreach_override, NULL);
4213 printf ("Override map \"%s\" END.\n", message);
4215 printf ("Override map \"%s\" EMPTY.\n", message);
4219 print_vtable_full (MonoClass *klass, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
4220 char *full_name = mono_type_full_name (&klass->byval_arg);
4224 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
4226 if (print_interfaces) {
4227 print_implemented_interfaces (klass);
4228 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
4231 if (klass->parent) {
4232 parent_size = klass->parent->vtable_size;
4236 for (i = 0; i < size; ++i) {
4237 MonoMethod *cm = vtable [i];
4238 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
4239 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
4241 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
4249 #if VERIFY_INTERFACE_VTABLE_CODE
4251 mono_method_try_get_vtable_index (MonoMethod *method)
4253 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4254 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4255 if (imethod->declaring->is_generic)
4256 return imethod->declaring->slot;
4258 return method->slot;
4262 mono_class_verify_vtable (MonoClass *klass)
4265 char *full_name = mono_type_full_name (&klass->byval_arg);
4267 printf ("*** Verifying VTable of class '%s' \n", full_name);
4271 if (!klass->methods)
4274 count = mono_class_method_count (klass);
4275 for (i = 0; i < count; ++i) {
4276 MonoMethod *cm = klass->methods [i];
4279 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4283 full_name = mono_method_full_name (cm, TRUE);
4285 slot = mono_method_try_get_vtable_index (cm);
4287 if (slot >= klass->vtable_size) {
4288 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, klass->vtable_size);
4292 if (slot >= 0 && klass->vtable [slot] != cm && (klass->vtable [slot])) {
4293 char *other_name = klass->vtable [slot] ? mono_method_full_name (klass->vtable [slot], TRUE) : g_strdup ("[null value]");
4294 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4295 g_free (other_name);
4298 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4305 print_unimplemented_interface_method_info (MonoClass *klass, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum)
4308 char *method_signature;
4311 for (index = 0; index < onum; ++index) {
4312 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)", im_slot, overrides [index*2+1]->name,
4313 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4315 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4316 type_name = mono_type_full_name (&klass->byval_arg);
4317 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s",
4318 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4319 g_free (method_signature);
4321 mono_class_setup_methods (klass);
4322 if (mono_class_has_failure (klass)) {
4323 char *name = mono_type_get_full_name (klass);
4324 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods", name);
4328 mcount = mono_class_get_method_count (klass);
4329 for (index = 0; index < mcount; ++index) {
4330 MonoMethod *cm = klass->methods [index];
4331 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4333 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)", cm->name, method_signature);
4334 g_free (method_signature);
4339 mono_method_get_method_definition (MonoMethod *method)
4341 while (method->is_inflated)
4342 method = ((MonoMethodInflated*)method)->declaring;
4347 verify_class_overrides (MonoClass *klass, MonoMethod **overrides, int onum)
4351 for (i = 0; i < onum; ++i) {
4352 MonoMethod *decl = overrides [i * 2];
4353 MonoMethod *body = overrides [i * 2 + 1];
4355 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (klass)) {
4356 mono_class_set_type_load_failure (klass, "Method belongs to a different class than the declared one");
4360 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4361 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4362 mono_class_set_type_load_failure (klass, "Method must not be static to override a base type");
4364 mono_class_set_type_load_failure (klass, "Method must be virtual to override a base type");
4368 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4369 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4370 mono_class_set_type_load_failure (klass, "Cannot override a static method in a base type");
4372 mono_class_set_type_load_failure (klass, "Cannot override a non virtual method in a base type");
4376 if (!mono_class_is_assignable_from_slow (decl->klass, klass)) {
4377 mono_class_set_type_load_failure (klass, "Method overrides a class or interface that is not extended or implemented by this type");
4381 body = mono_method_get_method_definition (body);
4382 decl = mono_method_get_method_definition (decl);
4384 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4385 char *body_name = mono_method_full_name (body, TRUE);
4386 char *decl_name = mono_method_full_name (decl, TRUE);
4387 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4397 mono_class_need_stelemref_method (MonoClass *klass)
4399 return klass->rank == 1 && MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg);
4403 * LOCKING: this is supposed to be called with the loader lock held.
4406 mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int onum, GList *in_setup)
4410 MonoMethod **vtable = NULL;
4411 int i, max_vtsize = 0, cur_slot = 0;
4413 GPtrArray *ifaces = NULL;
4414 GHashTable *override_map = NULL;
4416 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4417 int first_non_interface_slot;
4419 GSList *virt_methods = NULL, *l;
4420 int stelemref_slot = 0;
4425 if (overrides && !verify_class_overrides (klass, overrides, onum))
4428 ifaces = mono_class_get_implemented_interfaces (klass, &error);
4429 if (!mono_error_ok (&error)) {
4430 char *name = mono_type_get_full_name (klass);
4431 mono_class_set_type_load_failure (klass, "Could not resolve %s interfaces due to %s", name, mono_error_get_message (&error));
4433 mono_error_cleanup (&error);
4435 } else if (ifaces) {
4436 for (i = 0; i < ifaces->len; i++) {
4437 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
4438 max_vtsize += mono_class_get_method_count (ic);
4440 g_ptr_array_free (ifaces, TRUE);
4444 if (klass->parent) {
4445 mono_class_init (klass->parent);
4446 mono_class_setup_vtable_full (klass->parent, in_setup);
4448 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class failed to load"))
4451 max_vtsize += klass->parent->vtable_size;
4452 cur_slot = klass->parent->vtable_size;
4455 max_vtsize += mono_class_get_method_count (klass);
4457 /*Array have a slot for stelemref*/
4458 if (mono_class_need_stelemref_method (klass)) {
4459 stelemref_slot = cur_slot;
4464 /* printf ("METAINIT %s.%s\n", klass->name_space, klass->name); */
4466 cur_slot = setup_interface_offsets (klass, cur_slot, TRUE);
4467 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4470 max_iid = klass->max_interface_id;
4471 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4473 /* Optimized version for generic instances */
4474 if (mono_class_is_ginst (klass)) {
4476 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4479 mono_class_setup_vtable_full (gklass, in_setup);
4480 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Could not load generic definition"))
4483 tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * gklass->vtable_size);
4484 klass->vtable_size = gklass->vtable_size;
4485 for (i = 0; i < gklass->vtable_size; ++i)
4486 if (gklass->vtable [i]) {
4487 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], klass, mono_class_get_context (klass), &error);
4488 if (!mono_error_ok (&error)) {
4489 mono_class_set_type_load_failure (klass, "Could not inflate method due to %s", mono_error_get_message (&error));
4490 mono_error_cleanup (&error);
4494 tmp [i]->slot = gklass->vtable [i]->slot;
4496 mono_memory_barrier ();
4497 klass->vtable = tmp;
4499 /* Have to set method->slot for abstract virtual methods */
4500 if (klass->methods && gklass->methods) {
4501 int mcount = mono_class_get_method_count (klass);
4502 for (i = 0; i < mcount; ++i)
4503 if (klass->methods [i]->slot == -1)
4504 klass->methods [i]->slot = gklass->methods [i]->slot;
4510 vtable = (MonoMethod **)g_malloc0 (sizeof (gpointer) * max_vtsize);
4512 if (klass->parent && klass->parent->vtable_size) {
4513 MonoClass *parent = klass->parent;
4516 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4518 // Also inherit parent interface vtables, just as a starting point.
4519 // This is needed otherwise bug-77127.exe fails when the property methods
4520 // have different names in the iterface and the class, because for child
4521 // classes the ".override" information is not used anymore.
4522 for (i = 0; i < parent->interface_offsets_count; i++) {
4523 MonoClass *parent_interface = parent->interfaces_packed [i];
4524 int interface_offset = mono_class_interface_offset (klass, parent_interface);
4525 /*FIXME this is now dead code as this condition will never hold true.
4526 Since interface offsets are inherited then the offset of an interface implemented
4527 by a parent will never be the out of it's vtable boundary.
4529 if (interface_offset >= parent->vtable_size) {
4530 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4533 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4534 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4535 int mcount = mono_class_get_method_count (parent_interface);
4536 for (j = 0; j < mcount && !mono_class_has_failure (klass); j++) {
4537 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4538 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4539 parent_interface_offset + j, parent_interface_offset, j,
4540 interface_offset + j, interface_offset, j));
4547 /*Array have a slot for stelemref*/
4548 if (mono_class_need_stelemref_method (klass)) {
4549 MonoMethod *method = mono_marshal_get_virtual_stelemref (klass);
4551 method->slot = stelemref_slot;
4553 g_assert (method->slot == stelemref_slot);
4555 vtable [stelemref_slot] = method;
4558 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4559 /* override interface methods */
4560 for (i = 0; i < onum; i++) {
4561 MonoMethod *decl = overrides [i*2];
4562 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4564 dslot = mono_method_get_vtable_slot (decl);
4566 mono_class_set_type_load_failure (klass, "");
4570 dslot += mono_class_interface_offset (klass, decl->klass);
4571 vtable [dslot] = overrides [i*2 + 1];
4572 vtable [dslot]->slot = dslot;
4574 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4576 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4578 if (mono_security_core_clr_enabled ())
4579 mono_security_core_clr_check_override (klass, vtable [dslot], decl);
4582 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4583 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4586 * Create a list of virtual methods to avoid calling
4587 * mono_class_get_virtual_methods () which is slow because of the metadata
4591 gpointer iter = NULL;
4594 virt_methods = NULL;
4595 while ((cm = mono_class_get_virtual_methods (klass, &iter))) {
4596 virt_methods = g_slist_prepend (virt_methods, cm);
4598 if (mono_class_has_failure (klass))
4602 // Loop on all implemented interfaces...
4603 for (i = 0; i < klass->interface_offsets_count; i++) {
4604 MonoClass *parent = klass->parent;
4606 gboolean interface_is_explicitly_implemented_by_class;
4609 ic = klass->interfaces_packed [i];
4610 ic_offset = mono_class_interface_offset (klass, ic);
4612 mono_class_setup_methods (ic);
4613 if (mono_class_has_failure (ic))
4616 // Check if this interface is explicitly implemented (instead of just inherited)
4617 if (parent != NULL) {
4618 int implemented_interfaces_index;
4619 interface_is_explicitly_implemented_by_class = FALSE;
4620 for (implemented_interfaces_index = 0; implemented_interfaces_index < klass->interface_count; implemented_interfaces_index++) {
4621 if (ic == klass->interfaces [implemented_interfaces_index]) {
4622 interface_is_explicitly_implemented_by_class = TRUE;
4627 interface_is_explicitly_implemented_by_class = TRUE;
4630 // Loop on all interface methods...
4631 int mcount = mono_class_get_method_count (ic);
4632 for (im_index = 0; im_index < mcount; im_index++) {
4633 MonoMethod *im = ic->methods [im_index];
4634 int im_slot = ic_offset + im->slot;
4635 MonoMethod *override_im = (override_map != NULL) ? (MonoMethod *)g_hash_table_lookup (override_map, im) : NULL;
4637 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4640 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4642 // If there is an explicit implementation, just use it right away,
4643 // otherwise look for a matching method
4644 if (override_im == NULL) {
4648 // First look for a suitable method among the class methods
4649 for (l = virt_methods; l; l = l->next) {
4650 cm = (MonoMethod *)l->data;
4651 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)));
4652 if (check_interface_method_override (klass, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
4653 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4654 vtable [im_slot] = cm;
4655 /* Why do we need this? */
4660 TRACE_INTERFACE_VTABLE (printf ("\n"));
4661 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4665 // If the slot is still empty, look in all the inherited virtual methods...
4666 if ((vtable [im_slot] == NULL) && klass->parent != NULL) {
4667 MonoClass *parent = klass->parent;
4668 // Reverse order, so that last added methods are preferred
4669 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4670 MonoMethod *cm = parent->vtable [cm_index];
4672 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));
4673 if ((cm != NULL) && check_interface_method_override (klass, im, cm, FALSE, FALSE, TRUE)) {
4674 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4675 vtable [im_slot] = cm;
4676 /* Why do we need this? */
4682 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4684 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4688 g_assert (vtable [im_slot] == override_im);
4693 // If the class is not abstract, check that all its interface slots are full.
4694 // The check is done here and not directly at the end of the loop above because
4695 // it can happen (for injected generic array interfaces) that the same slot is
4696 // processed multiple times (those interfaces have overlapping slots), and it
4697 // will not always be the first pass the one that fills the slot.
4698 if (!mono_class_is_abstract (klass)) {
4699 for (i = 0; i < klass->interface_offsets_count; i++) {
4703 ic = klass->interfaces_packed [i];
4704 ic_offset = mono_class_interface_offset (klass, ic);
4706 int mcount = mono_class_get_method_count (ic);
4707 for (im_index = 0; im_index < mcount; im_index++) {
4708 MonoMethod *im = ic->methods [im_index];
4709 int im_slot = ic_offset + im->slot;
4711 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4714 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4715 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4716 if (vtable [im_slot] == NULL) {
4717 print_unimplemented_interface_method_info (klass, ic, im, im_slot, overrides, onum);
4724 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4725 for (l = virt_methods; l; l = l->next) {
4726 cm = (MonoMethod *)l->data;
4728 * If the method is REUSE_SLOT, we must check in the
4729 * base class for a method to override.
4731 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4733 for (k = klass->parent; k ; k = k->parent) {
4738 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4739 MonoMethodSignature *cmsig, *m1sig;
4741 cmsig = mono_method_signature (cm);
4742 m1sig = mono_method_signature (m1);
4744 if (!cmsig || !m1sig) {
4745 /* FIXME proper error message */
4746 mono_class_set_type_load_failure (klass, "");
4750 if (!strcmp(cm->name, m1->name) &&
4751 mono_metadata_signature_equal (cmsig, m1sig)) {
4753 if (mono_security_core_clr_enabled ())
4754 mono_security_core_clr_check_override (klass, cm, m1);
4756 slot = mono_method_get_vtable_slot (m1);
4760 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4761 char *body_name = mono_method_full_name (cm, TRUE);
4762 char *decl_name = mono_method_full_name (m1, TRUE);
4763 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4769 g_assert (cm->slot < max_vtsize);
4771 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4772 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4773 mono_method_full_name (m1, 1), m1,
4774 mono_method_full_name (cm, 1), cm));
4775 g_hash_table_insert (override_map, m1, cm);
4779 if (mono_class_has_failure (k))
4789 /*Non final newslot methods must be given a non-interface vtable slot*/
4790 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4794 cm->slot = cur_slot++;
4796 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4797 vtable [cm->slot] = cm;
4800 /* override non interface methods */
4801 for (i = 0; i < onum; i++) {
4802 MonoMethod *decl = overrides [i*2];
4803 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4804 g_assert (decl->slot != -1);
4805 vtable [decl->slot] = overrides [i*2 + 1];
4806 overrides [i * 2 + 1]->slot = decl->slot;
4808 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4809 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4810 mono_method_full_name (decl, 1), decl,
4811 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4812 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4814 if (mono_security_core_clr_enabled ())
4815 mono_security_core_clr_check_override (klass, vtable [decl->slot], decl);
4820 * If a method occupies more than one place in the vtable, and it is
4821 * overriden, then change the other occurances too.
4826 for (i = 0; i < max_vtsize; ++i)
4828 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4830 cm = (MonoMethod *)g_hash_table_lookup (override_map, vtable [i]);
4835 g_hash_table_destroy (override_map);
4836 override_map = NULL;
4839 g_slist_free (virt_methods);
4840 virt_methods = NULL;
4842 /* Ensure that all vtable slots are filled with concrete instance methods */
4843 if (!mono_class_is_abstract (klass)) {
4844 for (i = 0; i < cur_slot; ++i) {
4845 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4846 char *type_name = mono_type_get_full_name (klass);
4847 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4848 mono_class_set_type_load_failure (klass, "Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name);
4850 g_free (method_name);
4857 if (mono_class_is_ginst (klass)) {
4858 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4860 mono_class_init (gklass);
4862 klass->vtable_size = MAX (gklass->vtable_size, cur_slot);
4864 /* Check that the vtable_size value computed in mono_class_init () is correct */
4865 if (klass->vtable_size)
4866 g_assert (cur_slot == klass->vtable_size);
4867 klass->vtable_size = cur_slot;
4870 /* Try to share the vtable with our parent. */
4871 if (klass->parent && (klass->parent->vtable_size == klass->vtable_size) && (memcmp (klass->parent->vtable, vtable, sizeof (gpointer) * klass->vtable_size) == 0)) {
4872 mono_memory_barrier ();
4873 klass->vtable = klass->parent->vtable;
4875 MonoMethod **tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * klass->vtable_size);
4876 memcpy (tmp, vtable, sizeof (gpointer) * klass->vtable_size);
4877 mono_memory_barrier ();
4878 klass->vtable = tmp;
4881 DEBUG_INTERFACE_VTABLE (print_vtable_full (klass, klass->vtable, klass->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4882 if (mono_print_vtable) {
4885 print_implemented_interfaces (klass);
4887 for (i = 0; i <= max_iid; i++)
4888 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
4891 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&klass->byval_arg),
4892 klass->vtable_size, icount);
4894 for (i = 0; i < cur_slot; ++i) {
4899 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4900 mono_method_full_name (cm, TRUE));
4906 printf ("Interfaces %s.%s (max_iid = %d)\n", klass->name_space,
4907 klass->name, max_iid);
4909 for (i = 0; i < klass->interface_count; i++) {
4910 ic = klass->interfaces [i];
4911 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4912 mono_class_interface_offset (klass, ic),
4913 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4916 for (k = klass->parent; k ; k = k->parent) {
4917 for (i = 0; i < k->interface_count; i++) {
4918 ic = k->interfaces [i];
4919 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4920 mono_class_interface_offset (klass, ic),
4921 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4929 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (klass));
4934 char *name = mono_type_get_full_name (klass);
4935 mono_class_set_type_load_failure (klass, "VTable setup of type %s failed", name);
4939 g_hash_table_destroy (override_map);
4941 g_slist_free (virt_methods);
4946 * mono_method_get_vtable_slot:
4948 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4949 * LOCKING: Acquires the loader lock.
4951 * FIXME Use proper MonoError machinery here.
4954 mono_method_get_vtable_slot (MonoMethod *method)
4956 if (method->slot == -1) {
4957 mono_class_setup_vtable (method->klass);
4958 if (mono_class_has_failure (method->klass))
4960 if (method->slot == -1) {
4964 if (!mono_class_is_ginst (method->klass)) {
4965 g_assert (method->is_inflated);
4966 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4969 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4970 g_assert (mono_class_is_ginst (method->klass));
4971 gklass = mono_class_get_generic_class (method->klass)->container_class;
4972 mono_class_setup_methods (method->klass);
4973 g_assert (method->klass->methods);
4974 mcount = mono_class_get_method_count (method->klass);
4975 for (i = 0; i < mcount; ++i) {
4976 if (method->klass->methods [i] == method)
4979 g_assert (i < mcount);
4980 g_assert (gklass->methods);
4981 method->slot = gklass->methods [i]->slot;
4983 g_assert (method->slot != -1);
4985 return method->slot;
4989 * mono_method_get_vtable_index:
4992 * Returns the index into the runtime vtable to access the method or,
4993 * in the case of a virtual generic method, the virtual generic method
4994 * thunk. Returns -1 on failure.
4996 * FIXME Use proper MonoError machinery here.
4999 mono_method_get_vtable_index (MonoMethod *method)
5001 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
5002 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
5003 if (imethod->declaring->is_generic)
5004 return mono_method_get_vtable_slot (imethod->declaring);
5006 return mono_method_get_vtable_slot (method);
5009 static MonoMethod *default_ghc = NULL;
5010 static MonoMethod *default_finalize = NULL;
5011 static int finalize_slot = -1;
5012 static int ghc_slot = -1;
5015 initialize_object_slots (MonoClass *klass)
5020 if (klass == mono_defaults.object_class) {
5021 mono_class_setup_vtable (klass);
5022 for (i = 0; i < klass->vtable_size; ++i) {
5023 MonoMethod *cm = klass->vtable [i];
5025 if (!strcmp (cm->name, "GetHashCode"))
5027 else if (!strcmp (cm->name, "Finalize"))
5031 g_assert (ghc_slot > 0);
5032 default_ghc = klass->vtable [ghc_slot];
5034 g_assert (finalize_slot > 0);
5035 default_finalize = klass->vtable [finalize_slot];
5040 MonoMethod *array_method;
5042 } GenericArrayMethodInfo;
5044 static int generic_array_method_num = 0;
5045 static GenericArrayMethodInfo *generic_array_method_info = NULL;
5048 generic_array_methods (MonoClass *klass)
5050 int i, count_generic = 0, mcount;
5051 GList *list = NULL, *tmp;
5052 if (generic_array_method_num)
5053 return generic_array_method_num;
5054 mono_class_setup_methods (klass->parent); /*This is setting up System.Array*/
5055 g_assert (!mono_class_has_failure (klass->parent)); /*So hitting this assert is a huge problem*/
5056 mcount = mono_class_get_method_count (klass->parent);
5057 for (i = 0; i < mcount; i++) {
5058 MonoMethod *m = klass->parent->methods [i];
5059 if (!strncmp (m->name, "InternalArray__", 15)) {
5061 list = g_list_prepend (list, m);
5064 list = g_list_reverse (list);
5065 generic_array_method_info = (GenericArrayMethodInfo *)mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
5067 for (tmp = list; tmp; tmp = tmp->next) {
5068 const char *mname, *iname;
5070 MonoMethod *m = (MonoMethod *)tmp->data;
5071 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
5072 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
5074 generic_array_method_info [i].array_method = m;
5075 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
5076 iname = "System.Collections.Generic.ICollection`1.";
5077 mname = m->name + 27;
5078 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
5079 iname = "System.Collections.Generic.IEnumerable`1.";
5080 mname = m->name + 27;
5081 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
5082 iname = "System.Collections.Generic.IReadOnlyList`1.";
5083 mname = m->name + strlen (ireadonlylist_prefix);
5084 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
5085 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
5086 mname = m->name + strlen (ireadonlycollection_prefix);
5087 } else if (!strncmp (m->name, "InternalArray__", 15)) {
5088 iname = "System.Collections.Generic.IList`1.";
5089 mname = m->name + 15;
5091 g_assert_not_reached ();
5094 name = (gchar *)mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
5095 strcpy (name, iname);
5096 strcpy (name + strlen (iname), mname);
5097 generic_array_method_info [i].name = name;
5100 /*g_print ("array generic methods: %d\n", count_generic);*/
5102 generic_array_method_num = count_generic;
5104 return generic_array_method_num;
5108 setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos)
5110 MonoGenericContext tmp_context;
5113 tmp_context.class_inst = NULL;
5114 tmp_context.method_inst = mono_class_get_generic_class (iface)->context.class_inst;
5115 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
5117 for (i = 0; i < generic_array_method_num; i++) {
5119 MonoMethod *m = generic_array_method_info [i].array_method;
5120 MonoMethod *inflated;
5122 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
5123 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
5124 methods [pos++] = mono_marshal_get_generic_array_helper (klass, iface, generic_array_method_info [i].name, inflated);
5129 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
5131 int null_length = strlen ("(null)");
5132 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
5133 char *s = (char *)mono_image_alloc (image, len);
5136 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
5137 g_assert (result == len - 1);
5144 * @klass: the class to initialize
5146 * Compute the instance_size, class_size and other infos that cannot be
5147 * computed at mono_class_get() time. Also compute vtable_size if possible.
5148 * Returns TRUE on success or FALSE if there was a problem in loading
5149 * the type (incorrect assemblies, missing assemblies, methods, etc).
5150 * Initializes the following fields in @klass:
5151 * - all the fields initialized by mono_class_init_sizes ()
5156 * LOCKING: Acquires the loader lock.
5159 mono_class_init (MonoClass *klass)
5161 int i, vtable_size = 0, array_method_count = 0;
5162 MonoCachedClassInfo cached_info;
5163 gboolean has_cached_info;
5164 gboolean locked = FALSE;
5165 gboolean ghcimpl = FALSE;
5166 gboolean has_cctor = FALSE;
5167 int first_iface_slot = 0;
5171 /* Double-checking locking pattern */
5172 if (klass->inited || mono_class_has_failure (klass))
5173 return !mono_class_has_failure (klass);
5175 /*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/
5178 * This function can recursively call itself.
5180 GSList *init_list = (GSList *)mono_native_tls_get_value (init_pending_tls_id);
5181 if (g_slist_find (init_list, klass)) {
5182 mono_class_set_type_load_failure (klass, "Recursive type definition detected");
5185 init_list = g_slist_prepend (init_list, klass);
5186 mono_native_tls_set_value (init_pending_tls_id, init_list);
5189 * We want to avoid doing complicated work inside locks, so we compute all the required
5190 * information and write it to @klass inside a lock.
5193 if (mono_verifier_is_enabled_for_class (klass) && !mono_verifier_verify_class (klass)) {
5194 mono_class_set_type_load_failure (klass, "%s", concat_two_strings_with_zero (klass->image, klass->name, klass->image->assembly_name));
5198 if (klass->byval_arg.type == MONO_TYPE_ARRAY || klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5199 MonoClass *element_class = klass->element_class;
5200 if (!element_class->inited)
5201 mono_class_init (element_class);
5202 if (mono_class_set_type_load_failure_causedby_class (klass, element_class, "Could not load array element class"))
5206 mono_stats.initialized_class_count++;
5208 if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic) {
5209 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5211 mono_class_init (gklass);
5212 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic Type Definition failed to init"))
5215 mono_class_setup_interface_id (klass);
5218 if (klass->parent && !klass->parent->inited)
5219 mono_class_init (klass->parent);
5221 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
5223 /* Compute instance size etc. */
5224 init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
5225 if (mono_class_has_failure (klass))
5228 mono_class_setup_supertypes (klass);
5231 initialize_object_slots (klass);
5234 * Initialize the rest of the data without creating a generic vtable if possible.
5235 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5236 * also avoid computing a generic vtable.
5238 if (has_cached_info) {
5240 vtable_size = cached_info.vtable_size;
5241 ghcimpl = cached_info.ghcimpl;
5242 has_cctor = cached_info.has_cctor;
5243 } else if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5244 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5245 * The first slot if for array with.
5247 static int szarray_vtable_size[2] = { 0 };
5249 int slot = MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg) ? 0 : 1;
5252 if (!szarray_vtable_size [slot]) {
5253 mono_class_setup_vtable (klass);
5254 szarray_vtable_size [slot] = klass->vtable_size;
5255 vtable_size = klass->vtable_size;
5257 vtable_size = szarray_vtable_size[slot];
5259 } else if (mono_class_is_ginst (klass) && !MONO_CLASS_IS_INTERFACE (klass)) {
5260 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5262 /* Generic instance case */
5263 ghcimpl = gklass->ghcimpl;
5264 has_cctor = gklass->has_cctor;
5266 mono_class_setup_vtable (gklass);
5267 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to init"))
5270 vtable_size = gklass->vtable_size;
5274 /* ghcimpl is not currently used
5276 if (klass->parent) {
5277 MonoMethod *cmethod = klass->vtable [ghc_slot];
5278 if (cmethod->is_inflated)
5279 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5280 if (cmethod == default_ghc) {
5286 /* C# doesn't allow interfaces to have cctors */
5287 if (!MONO_CLASS_IS_INTERFACE (klass) || klass->image != mono_defaults.corlib) {
5288 MonoMethod *cmethod = NULL;
5290 if (mono_class_is_ginst (klass)) {
5291 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5293 /* Generic instance case */
5294 ghcimpl = gklass->ghcimpl;
5295 has_cctor = gklass->has_cctor;
5296 } else if (klass->type_token && !image_is_dynamic(klass->image)) {
5297 cmethod = find_method_in_metadata (klass, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5298 /* The find_method function ignores the 'flags' argument */
5299 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5302 mono_class_setup_methods (klass);
5303 if (mono_class_has_failure (klass))
5306 int mcount = mono_class_get_method_count (klass);
5307 for (i = 0; i < mcount; ++i) {
5308 MonoMethod *method = klass->methods [i];
5309 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5310 (strcmp (".cctor", method->name) == 0)) {
5320 array_method_count = 3 + (klass->rank > 1? 2: 1);
5322 if (klass->interface_count) {
5323 int count_generic = generic_array_methods (klass);
5324 array_method_count += klass->interface_count * count_generic;
5328 if (klass->parent) {
5329 if (!klass->parent->vtable_size)
5330 mono_class_setup_vtable (klass->parent);
5331 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class vtable failed to initialize"))
5333 g_assert (klass->parent->vtable_size);
5334 first_iface_slot = klass->parent->vtable_size;
5335 if (mono_class_need_stelemref_method (klass))
5340 * Do the actual changes to @klass inside the loader lock
5342 mono_loader_lock ();
5345 if (klass->inited || mono_class_has_failure (klass)) {
5346 mono_loader_unlock ();
5347 /* Somebody might have gotten in before us */
5348 return !mono_class_has_failure (klass);
5351 mono_stats.initialized_class_count++;
5353 if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic)
5354 mono_stats.generic_class_count++;
5356 if (mono_class_is_ginst (klass) || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
5357 klass->nested_classes_inited = TRUE;
5358 klass->ghcimpl = ghcimpl;
5359 klass->has_cctor = has_cctor;
5361 klass->vtable_size = vtable_size;
5362 if (has_cached_info) {
5363 klass->has_finalize = cached_info.has_finalize;
5364 klass->has_finalize_inited = TRUE;
5367 mono_class_set_method_count (klass, array_method_count);
5369 mono_loader_unlock ();
5372 setup_interface_offsets (klass, first_iface_slot, TRUE);
5374 if (mono_security_core_clr_enabled ())
5375 mono_security_core_clr_check_inheritance (klass);
5377 if (mono_class_is_ginst (klass) && !mono_verifier_class_is_valid_generic_instantiation (klass))
5378 mono_class_set_type_load_failure (klass, "Invalid generic instantiation");
5383 init_list = g_slist_remove (init_list, klass);
5384 mono_native_tls_set_value (init_pending_tls_id, init_list);
5386 /* Because of the double-checking locking pattern */
5387 mono_memory_barrier ();
5391 mono_loader_unlock ();
5393 return !mono_class_has_failure (klass);
5397 * mono_class_has_finalizer:
5399 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5403 mono_class_has_finalizer (MonoClass *klass)
5405 gboolean has_finalize = FALSE;
5407 if (klass->has_finalize_inited)
5408 return klass->has_finalize;
5410 /* Interfaces and valuetypes are not supposed to have finalizers */
5411 if (!(MONO_CLASS_IS_INTERFACE (klass) || klass->valuetype)) {
5412 MonoMethod *cmethod = NULL;
5414 if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5415 } else if (mono_class_is_ginst (klass)) {
5416 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5418 has_finalize = mono_class_has_finalizer (gklass);
5419 } else if (klass->parent && klass->parent->has_finalize) {
5420 has_finalize = TRUE;
5422 if (klass->parent) {
5424 * Can't search in metadata for a method named Finalize, because that
5425 * ignores overrides.
5427 mono_class_setup_vtable (klass);
5428 if (mono_class_has_failure (klass))
5431 cmethod = klass->vtable [finalize_slot];
5435 g_assert (klass->vtable_size > finalize_slot);
5437 if (klass->parent) {
5438 if (cmethod->is_inflated)
5439 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5440 if (cmethod != default_finalize)
5441 has_finalize = TRUE;
5447 mono_image_lock (klass->image);
5449 if (!klass->has_finalize_inited) {
5450 klass->has_finalize = has_finalize ? 1 : 0;
5452 mono_memory_barrier ();
5453 klass->has_finalize_inited = TRUE;
5456 mono_image_unlock (klass->image);
5458 return klass->has_finalize;
5462 mono_is_corlib_image (MonoImage *image)
5464 return image == mono_defaults.corlib;
5468 * LOCKING: this assumes the loader lock is held
5471 mono_class_setup_mono_type (MonoClass *klass)
5473 const char *name = klass->name;
5474 const char *nspace = klass->name_space;
5475 gboolean is_corlib = mono_is_corlib_image (klass->image);
5477 klass->this_arg.byref = 1;
5478 klass->this_arg.data.klass = klass;
5479 klass->this_arg.type = MONO_TYPE_CLASS;
5480 klass->byval_arg.data.klass = klass;
5481 klass->byval_arg.type = MONO_TYPE_CLASS;
5483 if (is_corlib && !strcmp (nspace, "System")) {
5484 if (!strcmp (name, "ValueType")) {
5486 * do not set the valuetype bit for System.ValueType.
5487 * klass->valuetype = 1;
5489 klass->blittable = TRUE;
5490 } else if (!strcmp (name, "Enum")) {
5492 * do not set the valuetype bit for System.Enum.
5493 * klass->valuetype = 1;
5495 klass->valuetype = 0;
5496 klass->enumtype = 0;
5497 } else if (!strcmp (name, "Object")) {
5498 klass->byval_arg.type = MONO_TYPE_OBJECT;
5499 klass->this_arg.type = MONO_TYPE_OBJECT;
5500 } else if (!strcmp (name, "String")) {
5501 klass->byval_arg.type = MONO_TYPE_STRING;
5502 klass->this_arg.type = MONO_TYPE_STRING;
5503 } else if (!strcmp (name, "TypedReference")) {
5504 klass->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5505 klass->this_arg.type = MONO_TYPE_TYPEDBYREF;
5509 if (klass->valuetype) {
5510 int t = MONO_TYPE_VALUETYPE;
5512 if (is_corlib && !strcmp (nspace, "System")) {
5515 if (!strcmp (name, "Boolean")) {
5516 t = MONO_TYPE_BOOLEAN;
5517 } else if (!strcmp(name, "Byte")) {
5519 klass->blittable = TRUE;
5523 if (!strcmp (name, "Char")) {
5528 if (!strcmp (name, "Double")) {
5530 klass->blittable = TRUE;
5534 if (!strcmp (name, "Int32")) {
5536 klass->blittable = TRUE;
5537 } else if (!strcmp(name, "Int16")) {
5539 klass->blittable = TRUE;
5540 } else if (!strcmp(name, "Int64")) {
5542 klass->blittable = TRUE;
5543 } else if (!strcmp(name, "IntPtr")) {
5545 klass->blittable = TRUE;
5549 if (!strcmp (name, "Single")) {
5551 klass->blittable = TRUE;
5552 } else if (!strcmp(name, "SByte")) {
5554 klass->blittable = TRUE;
5558 if (!strcmp (name, "UInt32")) {
5560 klass->blittable = TRUE;
5561 } else if (!strcmp(name, "UInt16")) {
5563 klass->blittable = TRUE;
5564 } else if (!strcmp(name, "UInt64")) {
5566 klass->blittable = TRUE;
5567 } else if (!strcmp(name, "UIntPtr")) {
5569 klass->blittable = TRUE;
5573 if (!strcmp (name, "TypedReference")) {
5574 t = MONO_TYPE_TYPEDBYREF;
5575 klass->blittable = TRUE;
5579 if (!strcmp (name, "Void")) {
5587 klass->byval_arg.type = (MonoTypeEnum)t;
5588 klass->this_arg.type = (MonoTypeEnum)t;
5591 if (MONO_CLASS_IS_INTERFACE (klass))
5592 klass->interface_id = mono_get_unique_iid (klass);
5597 * COM initialization is delayed until needed.
5598 * However when a [ComImport] attribute is present on a type it will trigger
5599 * the initialization. This is not a problem unless the BCL being executed
5600 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5603 init_com_from_comimport (MonoClass *klass)
5605 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5606 if (mono_security_core_clr_enabled ()) {
5607 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5608 if (!mono_security_core_clr_determine_platform_image (klass->image)) {
5609 /* but it can not be made available for application (i.e. user code) since all COM calls
5610 * are considered native calls. In this case we fail with a TypeLoadException (just like
5611 * Silverlight 2 does */
5612 mono_class_set_type_load_failure (klass, "");
5617 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5619 #endif /*DISABLE_COM*/
5622 * LOCKING: this assumes the loader lock is held
5625 mono_class_setup_parent (MonoClass *klass, MonoClass *parent)
5627 gboolean system_namespace;
5628 gboolean is_corlib = mono_is_corlib_image (klass->image);
5630 system_namespace = !strcmp (klass->name_space, "System") && is_corlib;
5632 /* if root of the hierarchy */
5633 if (system_namespace && !strcmp (klass->name, "Object")) {
5634 klass->parent = NULL;
5635 klass->instance_size = sizeof (MonoObject);
5638 if (!strcmp (klass->name, "<Module>")) {
5639 klass->parent = NULL;
5640 klass->instance_size = 0;
5644 if (!MONO_CLASS_IS_INTERFACE (klass)) {
5645 /* Imported COM Objects always derive from __ComObject. */
5647 if (MONO_CLASS_IS_IMPORT (klass)) {
5648 init_com_from_comimport (klass);
5649 if (parent == mono_defaults.object_class)
5650 parent = mono_class_get_com_object_class ();
5654 /* set the parent to something useful and safe, but mark the type as broken */
5655 parent = mono_defaults.object_class;
5656 mono_class_set_type_load_failure (klass, "");
5660 klass->parent = parent;
5662 if (mono_class_is_ginst (parent) && !parent->name) {
5664 * If the parent is a generic instance, we may get
5665 * called before it is fully initialized, especially
5666 * before it has its name.
5671 #ifndef DISABLE_REMOTING
5672 klass->marshalbyref = parent->marshalbyref;
5673 klass->contextbound = parent->contextbound;
5676 klass->delegate = parent->delegate;
5678 if (MONO_CLASS_IS_IMPORT (klass) || mono_class_is_com_object (parent))
5679 mono_class_set_is_com_object (klass);
5681 if (system_namespace) {
5682 #ifndef DISABLE_REMOTING
5683 if (klass->name [0] == 'M' && !strcmp (klass->name, "MarshalByRefObject"))
5684 klass->marshalbyref = 1;
5686 if (klass->name [0] == 'C' && !strcmp (klass->name, "ContextBoundObject"))
5687 klass->contextbound = 1;
5689 if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate"))
5690 klass->delegate = 1;
5693 if (klass->parent->enumtype || (mono_is_corlib_image (klass->parent->image) && (strcmp (klass->parent->name, "ValueType") == 0) &&
5694 (strcmp (klass->parent->name_space, "System") == 0)))
5695 klass->valuetype = 1;
5696 if (mono_is_corlib_image (klass->parent->image) && ((strcmp (klass->parent->name, "Enum") == 0) && (strcmp (klass->parent->name_space, "System") == 0))) {
5697 klass->valuetype = klass->enumtype = 1;
5699 /*klass->enumtype = klass->parent->enumtype; */
5701 /* initialize com types if COM interfaces are present */
5703 if (MONO_CLASS_IS_IMPORT (klass))
5704 init_com_from_comimport (klass);
5706 klass->parent = NULL;
5712 * mono_class_setup_supertypes:
5715 * Build the data structure needed to make fast type checks work.
5716 * This currently sets two fields in @class:
5717 * - idepth: distance between @class and System.Object in the type
5719 * - supertypes: array of classes: each element has a class in the hierarchy
5720 * starting from @class up to System.Object
5722 * LOCKING: Acquires the loader lock.
5725 mono_class_setup_supertypes (MonoClass *klass)
5728 MonoClass **supertypes;
5730 mono_atomic_load_acquire (supertypes, MonoClass **, &klass->supertypes);
5734 if (klass->parent && !klass->parent->supertypes)
5735 mono_class_setup_supertypes (klass->parent);
5737 idepth = klass->parent->idepth + 1;
5741 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, idepth);
5742 supertypes = (MonoClass **)mono_class_alloc0 (klass, sizeof (MonoClass *) * ms);
5744 if (klass->parent) {
5745 CHECKED_METADATA_WRITE_PTR ( supertypes [idepth - 1] , klass );
5748 for (supertype_idx = 0; supertype_idx < klass->parent->idepth; supertype_idx++)
5749 CHECKED_METADATA_WRITE_PTR ( supertypes [supertype_idx] , klass->parent->supertypes [supertype_idx] );
5751 CHECKED_METADATA_WRITE_PTR ( supertypes [0] , klass );
5754 mono_memory_barrier ();
5756 mono_loader_lock ();
5757 klass->idepth = idepth;
5758 /* Needed so idepth is visible before supertypes is set */
5759 mono_memory_barrier ();
5760 klass->supertypes = supertypes;
5761 mono_loader_unlock ();
5765 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5767 MonoClass *gtd = (MonoClass*)user_data;
5768 /* Only try to fix generic instances of @gtd */
5769 if (mono_class_get_generic_class (gclass)->container_class != gtd)
5772 /* Check if the generic instance has no parent. */
5773 if (gtd->parent && !gclass->parent)
5774 mono_generic_class_setup_parent (gclass, gtd);
5780 mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char *msg)
5782 mono_class_set_type_load_failure (klass, "%s", msg);
5783 mono_error_set_type_load_class (error, klass, "%s", msg);
5787 * mono_class_create_from_typedef:
5788 * @image: image where the token is valid
5789 * @type_token: typedef token
5790 * @error: used to return any error found while creating the type
5792 * Create the MonoClass* representing the specified type token.
5793 * @type_token must be a TypeDef token.
5795 * FIXME: don't return NULL on failure, just the the caller figure it out.
5798 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5800 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5801 MonoClass *klass, *parent = NULL;
5802 guint32 cols [MONO_TYPEDEF_SIZE];
5803 guint32 cols_next [MONO_TYPEDEF_SIZE];
5804 guint tidx = mono_metadata_token_index (type_token);
5805 MonoGenericContext *context = NULL;
5806 const char *name, *nspace;
5808 MonoClass **interfaces;
5809 guint32 field_last, method_last;
5810 guint32 nesting_tokeen;
5812 mono_error_init (error);
5814 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5815 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5819 mono_loader_lock ();
5821 if ((klass = (MonoClass *)mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5822 mono_loader_unlock ();
5826 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5828 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5829 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5831 if (mono_metadata_has_generic_params (image, type_token)) {
5832 klass = mono_image_alloc0 (image, sizeof (MonoClassGtd));
5833 klass->class_kind = MONO_CLASS_GTD;
5834 classes_size += sizeof (MonoClassGtd);
5837 klass = mono_image_alloc0 (image, sizeof (MonoClassDef));
5838 klass->class_kind = MONO_CLASS_DEF;
5839 classes_size += sizeof (MonoClassDef);
5844 klass->name_space = nspace;
5846 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5848 klass->image = image;
5849 klass->type_token = type_token;
5850 mono_class_set_flags (klass, cols [MONO_TYPEDEF_FLAGS]);
5852 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
5855 * Check whether we're a generic type definition.
5857 if (mono_class_is_gtd (klass)) {
5858 MonoGenericContainer *generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
5859 generic_container->owner.klass = klass;
5860 generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
5861 context = &generic_container->context;
5862 mono_class_set_generic_container (klass, generic_container);
5863 enable_gclass_recording ();
5866 if (cols [MONO_TYPEDEF_EXTENDS]) {
5868 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5870 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5871 /*WARNING: this must satisfy mono_metadata_type_hash*/
5872 klass->this_arg.byref = 1;
5873 klass->this_arg.data.klass = klass;
5874 klass->this_arg.type = MONO_TYPE_CLASS;
5875 klass->byval_arg.data.klass = klass;
5876 klass->byval_arg.type = MONO_TYPE_CLASS;
5878 parent = mono_class_get_checked (image, parent_token, error);
5879 if (parent && context) /* Always inflate */
5880 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5882 if (parent == NULL) {
5883 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5884 goto parent_failure;
5887 for (tmp = parent; tmp; tmp = tmp->parent) {
5889 mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
5890 goto parent_failure;
5892 if (mono_class_is_gtd (klass) && mono_class_is_ginst (tmp) && mono_class_get_generic_class (tmp)->container_class == klass) {
5893 mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
5894 goto parent_failure;
5899 mono_class_setup_parent (klass, parent);
5901 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5902 mono_class_setup_mono_type (klass);
5904 if (mono_class_is_gtd (klass))
5905 disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
5908 * This might access klass->byval_arg for recursion generated by generic constraints,
5909 * so it has to come after setup_mono_type ().
5911 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5912 klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5913 if (!mono_error_ok (error)) {
5914 /*FIXME implement a mono_class_set_failure_from_mono_error */
5915 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5916 mono_loader_unlock ();
5917 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5922 if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5926 if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5930 klass->cast_class = klass->element_class = klass;
5932 if (!klass->enumtype) {
5933 if (!mono_metadata_interfaces_from_typedef_full (
5934 image, type_token, &interfaces, &icount, FALSE, context, error)){
5936 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5937 mono_loader_unlock ();
5938 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5942 /* This is required now that it is possible for more than 2^16 interfaces to exist. */
5943 g_assert(icount <= 65535);
5945 klass->interfaces = interfaces;
5946 klass->interface_count = icount;
5947 klass->interfaces_inited = 1;
5950 /*g_print ("Load class %s\n", name);*/
5953 * Compute the field and method lists
5955 int first_field_idx = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5956 mono_class_set_first_field_idx (klass, first_field_idx);
5957 int first_method_idx = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5958 mono_class_set_first_method_idx (klass, first_method_idx);
5960 if (tt->rows > tidx){
5961 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5962 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5963 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5965 field_last = image->tables [MONO_TABLE_FIELD].rows;
5966 method_last = image->tables [MONO_TABLE_METHOD].rows;
5969 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5970 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5971 mono_class_set_field_count (klass, field_last - first_field_idx);
5972 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5973 mono_class_set_method_count (klass, method_last - first_method_idx);
5975 /* reserve space to store vector pointer in arrays */
5976 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5977 klass->instance_size += 2 * sizeof (gpointer);
5978 g_assert (mono_class_get_field_count (klass) == 0);
5981 if (klass->enumtype) {
5982 MonoType *enum_basetype = mono_class_find_enum_basetype (klass, error);
5983 if (!enum_basetype) {
5984 /*set it to a default value as the whole runtime can't handle this to be null*/
5985 klass->cast_class = klass->element_class = mono_defaults.int32_class;
5986 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5987 mono_loader_unlock ();
5988 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5991 klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
5995 * If we're a generic type definition, load the constraints.
5996 * We must do this after the class has been constructed to make certain recursive scenarios
5999 if (mono_class_is_gtd (klass) && !mono_metadata_load_generic_param_constraints_checked (image, type_token, mono_class_get_generic_container (klass), error)) {
6000 mono_class_set_type_load_failure (klass, "Could not load generic parameter constrains due to %s", mono_error_get_message (error));
6001 mono_loader_unlock ();
6002 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
6006 if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
6007 if (!strncmp (name, "Vector", 6))
6008 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");
6009 } else if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "System.Numerics") && !strcmp (nspace, "System.Numerics")) {
6010 if (!strcmp (name, "Vector2") || !strcmp (name, "Vector3") || !strcmp (name, "Vector4"))
6011 klass->simd_type = 1;
6012 } else if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "System.Numerics.Vectors") && !strcmp (nspace, "System.Numerics")) {
6013 if (!strcmp (name, "Vector`1"))
6014 klass->simd_type = 1;
6017 mono_loader_unlock ();
6019 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6024 mono_class_setup_mono_type (klass);
6025 mono_loader_unlock ();
6026 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
6030 /** Is klass a Nullable<T> ginst? */
6032 mono_class_is_nullable (MonoClass *klass)
6034 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
6035 return gklass && gklass->container_class == mono_defaults.generic_nullable_class;
6039 /** if klass is T? return T */
6041 mono_class_get_nullable_param (MonoClass *klass)
6043 g_assert (mono_class_is_nullable (klass));
6044 return mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
6048 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
6052 MonoGenericClass *gclass = mono_class_get_generic_class (klass);
6054 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
6055 if (!mono_error_ok (&error)) {
6056 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
6057 klass->parent = mono_defaults.object_class;
6058 mono_class_set_type_load_failure (klass, "Parent is a generic type instantiation that failed due to: %s", mono_error_get_message (&error));
6059 mono_error_cleanup (&error);
6063 mono_class_setup_parent (klass, klass->parent);
6065 if (klass->enumtype) {
6066 klass->cast_class = gtd->cast_class;
6067 klass->element_class = gtd->element_class;
6073 * Create the `MonoClass' for an instantiation of a generic type.
6074 * We only do this if we actually need it.
6077 mono_generic_class_get_class (MonoGenericClass *gclass)
6079 MonoClass *klass, *gklass;
6081 if (gclass->cached_class)
6082 return gclass->cached_class;
6084 klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClassGenericInst));
6086 gklass = gclass->container_class;
6088 if (gklass->nested_in) {
6089 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
6090 klass->nested_in = gklass->nested_in;
6093 klass->name = gklass->name;
6094 klass->name_space = gklass->name_space;
6096 klass->image = gklass->image;
6097 klass->type_token = gklass->type_token;
6099 klass->class_kind = MONO_CLASS_GINST;
6101 ((MonoClassGenericInst*)klass)->generic_class = gclass;
6103 klass->byval_arg.type = MONO_TYPE_GENERICINST;
6104 klass->this_arg.type = klass->byval_arg.type;
6105 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
6106 klass->this_arg.byref = TRUE;
6107 klass->enumtype = gklass->enumtype;
6108 klass->valuetype = gklass->valuetype;
6109 klass->simd_type = gklass->simd_type;
6111 klass->cast_class = klass->element_class = klass;
6113 if (gclass->is_dynamic) {
6115 * 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.
6116 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
6117 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
6119 if (!gklass->wastypebuilder)
6122 if (klass->enumtype) {
6124 * For enums, gklass->fields might not been set, but instance_size etc. is
6125 * already set in mono_reflection_create_internal_class (). For non-enums,
6126 * these will be computed normally in mono_class_layout_fields ().
6128 klass->instance_size = gklass->instance_size;
6129 klass->sizes.class_size = gklass->sizes.class_size;
6130 klass->size_inited = 1;
6134 mono_loader_lock ();
6136 if (gclass->cached_class) {
6137 mono_loader_unlock ();
6138 return gclass->cached_class;
6141 if (record_gclass_instantiation > 0)
6142 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
6144 if (mono_class_is_nullable (klass))
6145 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
6147 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6149 mono_generic_class_setup_parent (klass, gklass);
6151 if (gclass->is_dynamic)
6152 mono_class_setup_supertypes (klass);
6154 mono_memory_barrier ();
6155 gclass->cached_class = klass;
6157 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6159 ++class_ginst_count;
6160 inflated_classes_size += sizeof (MonoClassGenericInst);
6162 mono_loader_unlock ();
6168 get_image_for_container (MonoGenericContainer *container)
6171 if (container->is_anonymous) {
6172 result = container->owner.image;
6175 if (container->is_method) {
6176 MonoMethod *method = container->owner.method;
6177 g_assert_checked (method);
6178 klass = method->klass;
6180 klass = container->owner.klass;
6182 g_assert_checked (klass);
6183 result = klass->image;
6190 get_image_for_generic_param (MonoGenericParam *param)
6192 MonoGenericContainer *container = mono_generic_param_owner (param);
6193 g_assert_checked (container);
6194 return get_image_for_container (container);
6197 // Make a string in the designated image consisting of a single integer.
6198 #define INT_STRING_SIZE 16
6200 make_generic_name_string (MonoImage *image, int num)
6202 char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
6203 g_snprintf (name, INT_STRING_SIZE, "%d", num);
6207 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
6208 // pinfo is derived from param by the caller for us.
6210 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
6212 MonoClass *klass, **ptr;
6214 MonoGenericContainer *container = mono_generic_param_owner (param);
6215 g_assert_checked (container);
6217 MonoImage *image = get_image_for_container (container);
6218 gboolean is_mvar = container->is_method;
6219 gboolean is_anonymous = container->is_anonymous;
6221 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassGenericParam));
6222 klass->class_kind = MONO_CLASS_GPARAM;
6223 classes_size += sizeof (MonoClassGenericParam);
6224 ++class_gparam_count;
6227 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
6229 int n = mono_generic_param_num (param);
6230 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
6234 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , "" );
6235 } else if (is_mvar) {
6236 MonoMethod *omethod = container->owner.method;
6237 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
6239 MonoClass *oklass = container->owner.klass;
6240 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
6243 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6245 // Count non-NULL items in pinfo->constraints
6248 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6252 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6253 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
6255 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
6256 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
6258 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
6261 if (count - pos > 0) {
6262 klass->interface_count = count - pos;
6263 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
6264 klass->interfaces_inited = TRUE;
6265 for (i = pos; i < count; i++)
6266 CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
6269 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
6271 klass->inited = TRUE;
6272 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class , klass );
6273 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
6275 klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6276 klass->this_arg.type = klass->byval_arg.type;
6277 CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param , param );
6278 CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
6279 klass->this_arg.byref = TRUE;
6281 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6282 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6284 /*Init these fields to sane values*/
6285 klass->min_align = 1;
6287 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6288 * constrained to, the JIT depends on this.
6290 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6291 mono_memory_barrier ();
6292 klass->size_inited = 1;
6294 mono_class_setup_supertypes (klass);
6296 if (count - pos > 0) {
6297 mono_class_setup_vtable (klass->parent);
6298 if (mono_class_has_failure (klass->parent))
6299 mono_class_set_type_load_failure (klass, "Failed to setup parent interfaces");
6301 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6307 #define FAST_CACHE_SIZE 16
6310 * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6311 * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6312 * we cache the MonoClasses.
6313 * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6314 * LOCKING: Takes the image lock depending on @take_lock.
6317 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6319 int n = mono_generic_param_num (param);
6320 MonoImage *image = get_image_for_generic_param (param);
6321 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6322 MonoClass *klass = NULL;
6327 // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6328 // For high numbers or constraints we have to use pointer hashes.
6329 if (param->gshared_constraint) {
6330 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6333 mono_image_lock (image);
6334 klass = (MonoClass *)g_hash_table_lookup (ht, param);
6336 mono_image_unlock (image);
6341 if (n < FAST_CACHE_SIZE) {
6343 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6345 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6347 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6350 mono_image_lock (image);
6351 klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6353 mono_image_unlock (image);
6360 * LOCKING: Image lock (param->image) must be held
6363 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6365 int n = mono_generic_param_num (param);
6366 MonoImage *image = get_image_for_generic_param (param);
6367 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6371 if (param->gshared_constraint) {
6372 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6374 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6375 mono_memory_barrier ();
6377 image->mvar_cache_constrained = ht;
6379 image->var_cache_constrained = ht;
6381 g_hash_table_insert (ht, param, klass);
6382 } else if (n < FAST_CACHE_SIZE) {
6384 /* Requires locking to avoid droping an already published class */
6385 if (!image->mvar_cache_fast)
6386 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6387 image->mvar_cache_fast [n] = klass;
6389 if (!image->var_cache_fast)
6390 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6391 image->var_cache_fast [n] = klass;
6394 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6396 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6398 ht = g_hash_table_new (NULL, NULL);
6399 mono_memory_barrier ();
6401 image->mvar_cache_slow = ht;
6403 image->var_cache_slow = ht;
6406 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6411 * LOCKING: Acquires the image lock (@image).
6414 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6416 MonoImage *image = get_image_for_generic_param (param);
6417 MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6418 MonoClass *klass, *klass2;
6420 // If a klass already exists for this object and is cached, return it.
6421 if (pinfo) // Non-anonymous
6422 klass = pinfo->pklass;
6424 klass = get_anon_gparam_class (param, TRUE);
6429 // Create a new klass
6430 klass = make_generic_param_class (param, pinfo);
6432 // Now we need to cache the klass we created.
6433 // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6434 // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6435 // and allow our newly-created klass object to just leak.
6436 mono_memory_barrier ();
6438 mono_image_lock (image);
6440 // Here "klass2" refers to the klass potentially created by the other thread.
6441 if (pinfo) // Repeat check from above
6442 klass2 = pinfo->pklass;
6444 klass2 = get_anon_gparam_class (param, FALSE);
6451 pinfo->pklass = klass;
6453 set_anon_gparam_class (param, klass);
6455 mono_image_unlock (image);
6457 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6459 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED); // Alert profiler about botched class create
6461 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6467 * mono_class_from_generic_parameter:
6468 * @param: Parameter to find/construct a class for.
6469 * @arg2: Is ignored.
6470 * @arg3: Is ignored.
6473 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6475 return mono_class_from_generic_parameter_internal (param);
6479 mono_ptr_class_get (MonoType *type)
6482 MonoClass *el_class;
6486 el_class = mono_class_from_mono_type (type);
6487 image = el_class->image;
6489 mono_image_lock (image);
6490 if (image->ptr_cache) {
6491 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6492 mono_image_unlock (image);
6496 mono_image_unlock (image);
6498 result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassPointer));
6500 classes_size += sizeof (MonoClassPointer);
6501 ++class_pointer_count;
6503 result->parent = NULL; /* no parent for PTR types */
6504 result->name_space = el_class->name_space;
6505 name = g_strdup_printf ("%s*", el_class->name);
6506 result->name = mono_image_strdup (image, name);
6507 result->class_kind = MONO_CLASS_POINTER;
6510 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6512 result->image = el_class->image;
6513 result->inited = TRUE;
6514 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6515 result->cast_class = result->element_class = el_class;
6516 result->blittable = TRUE;
6518 result->byval_arg.type = MONO_TYPE_PTR;
6519 result->this_arg.type = result->byval_arg.type;
6520 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6521 result->this_arg.byref = TRUE;
6523 mono_class_setup_supertypes (result);
6525 mono_image_lock (image);
6526 if (image->ptr_cache) {
6528 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6529 mono_image_unlock (image);
6530 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6534 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6536 g_hash_table_insert (image->ptr_cache, el_class, result);
6537 mono_image_unlock (image);
6539 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6545 mono_fnptr_class_get (MonoMethodSignature *sig)
6547 MonoClass *result, *cached;
6548 static GHashTable *ptr_hash = NULL;
6550 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6552 mono_loader_lock ();
6554 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6555 cached = (MonoClass *)g_hash_table_lookup (ptr_hash, sig);
6556 mono_loader_unlock ();
6560 result = g_new0 (MonoClass, 1);
6562 result->parent = NULL; /* no parent for PTR types */
6563 result->name_space = "System";
6564 result->name = "MonoFNPtrFakeClass";
6565 result->class_kind = MONO_CLASS_POINTER;
6567 result->image = mono_defaults.corlib; /* need to fix... */
6568 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6569 result->cast_class = result->element_class = result;
6570 result->byval_arg.type = MONO_TYPE_FNPTR;
6571 result->this_arg.type = result->byval_arg.type;
6572 result->this_arg.data.method = result->byval_arg.data.method = sig;
6573 result->this_arg.byref = TRUE;
6574 result->blittable = TRUE;
6575 result->inited = TRUE;
6577 mono_class_setup_supertypes (result);
6579 mono_loader_lock ();
6581 cached = (MonoClass *)g_hash_table_lookup (ptr_hash, sig);
6584 mono_loader_unlock ();
6588 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6590 classes_size += sizeof (MonoClassPointer);
6591 ++class_pointer_count;
6593 g_hash_table_insert (ptr_hash, sig, result);
6595 mono_loader_unlock ();
6597 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6603 * mono_class_from_mono_type:
6604 * @type: describes the type to return
6606 * This returns a MonoClass for the specified MonoType, the value is never NULL.
6609 mono_class_from_mono_type (MonoType *type)
6611 switch (type->type) {
6612 case MONO_TYPE_OBJECT:
6613 return type->data.klass? type->data.klass: mono_defaults.object_class;
6614 case MONO_TYPE_VOID:
6615 return type->data.klass? type->data.klass: mono_defaults.void_class;
6616 case MONO_TYPE_BOOLEAN:
6617 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6618 case MONO_TYPE_CHAR:
6619 return type->data.klass? type->data.klass: mono_defaults.char_class;
6621 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6623 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6625 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6627 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6629 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6631 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6633 return type->data.klass? type->data.klass: mono_defaults.int_class;
6635 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6637 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6639 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6641 return type->data.klass? type->data.klass: mono_defaults.single_class;
6643 return type->data.klass? type->data.klass: mono_defaults.double_class;
6644 case MONO_TYPE_STRING:
6645 return type->data.klass? type->data.klass: mono_defaults.string_class;
6646 case MONO_TYPE_TYPEDBYREF:
6647 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6648 case MONO_TYPE_ARRAY:
6649 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6651 return mono_ptr_class_get (type->data.type);
6652 case MONO_TYPE_FNPTR:
6653 return mono_fnptr_class_get (type->data.method);
6654 case MONO_TYPE_SZARRAY:
6655 return mono_array_class_get (type->data.klass, 1);
6656 case MONO_TYPE_CLASS:
6657 case MONO_TYPE_VALUETYPE:
6658 return type->data.klass;
6659 case MONO_TYPE_GENERICINST:
6660 return mono_generic_class_get_class (type->data.generic_class);
6661 case MONO_TYPE_MVAR:
6663 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6665 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6666 g_assert_not_reached ();
6669 // Yes, this returns NULL, even if it is documented as not doing so, but there
6670 // is no way for the code to make it this far, due to the assert above.
6675 * mono_type_retrieve_from_typespec
6676 * @image: context where the image is created
6677 * @type_spec: typespec token
6678 * @context: the generic context used to evaluate generic instantiations in
6681 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6683 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6685 *did_inflate = FALSE;
6690 if (context && (context->class_inst || context->method_inst)) {
6691 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6693 if (!mono_error_ok (error)) {
6699 *did_inflate = TRUE;
6706 * mono_class_create_from_typespec
6707 * @image: context where the image is created
6708 * @type_spec: typespec token
6709 * @context: the generic context used to evaluate generic instantiations in
6712 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6715 gboolean inflated = FALSE;
6716 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6717 return_val_if_nok (error, NULL);
6718 ret = mono_class_from_mono_type (t);
6720 mono_metadata_free_type (t);
6725 * mono_bounded_array_class_get:
6726 * @element_class: element class
6727 * @rank: the dimension of the array class
6728 * @bounded: whenever the array has non-zero bounds
6730 * Returns: A class object describing the array with element type @element_type and
6734 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6737 MonoClass *klass, *cached, *k;
6738 MonoClass *parent = NULL;
6739 GSList *list, *rootlist = NULL;
6743 g_assert (rank <= 255);
6746 /* bounded only matters for one-dimensional arrays */
6749 image = eclass->image;
6753 if (rank == 1 && !bounded) {
6755 * This case is very frequent not just during compilation because of calls
6756 * from mono_class_from_mono_type (), mono_array_new (),
6757 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6759 mono_os_mutex_lock (&image->szarray_cache_lock);
6760 if (!image->szarray_cache)
6761 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6762 cached = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6763 mono_os_mutex_unlock (&image->szarray_cache_lock);
6765 mono_loader_lock ();
6766 if (!image->array_cache)
6767 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6768 rootlist = (GSList *)g_hash_table_lookup (image->array_cache, eclass);
6769 for (list = rootlist; list; list = list->next) {
6770 k = (MonoClass *)list->data;
6771 if ((k->rank == rank) && (k->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6776 mono_loader_unlock ();
6781 parent = mono_defaults.array_class;
6782 if (!parent->inited)
6783 mono_class_init (parent);
6785 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassArray));
6787 klass->image = image;
6788 klass->name_space = eclass->name_space;
6789 klass->class_kind = MONO_CLASS_ARRAY;
6791 nsize = strlen (eclass->name);
6792 name = (char *)g_malloc (nsize + 2 + rank + 1);
6793 memcpy (name, eclass->name, nsize);
6796 memset (name + nsize + 1, ',', rank - 1);
6798 name [nsize + rank] = '*';
6799 name [nsize + rank + bounded] = ']';
6800 name [nsize + rank + bounded + 1] = 0;
6801 klass->name = mono_image_strdup (image, name);
6804 klass->type_token = 0;
6805 klass->parent = parent;
6806 klass->instance_size = mono_class_instance_size (klass->parent);
6808 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6809 /*Arrays of those two types are invalid.*/
6810 MonoError prepared_error;
6811 mono_error_init (&prepared_error);
6812 mono_error_set_invalid_program (&prepared_error, "Arrays of void or System.TypedReference types are invalid.");
6813 mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6814 mono_error_cleanup (&prepared_error);
6815 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6816 guint32 ref_info_handle = mono_class_get_ref_info_handle (eclass);
6817 if (!ref_info_handle || eclass->wastypebuilder) {
6818 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6819 g_assert (ref_info_handle && !eclass->wastypebuilder);
6821 /* element_size -1 is ok as this is not an instantitable type*/
6822 klass->sizes.element_size = -1;
6824 klass->sizes.element_size = mono_class_array_element_size (eclass);
6826 mono_class_setup_supertypes (klass);
6828 if (mono_class_is_ginst (eclass))
6829 mono_class_init (eclass);
6830 if (!eclass->size_inited)
6831 mono_class_setup_fields (eclass);
6832 mono_class_set_type_load_failure_causedby_class (klass, eclass, "Could not load array element type");
6833 /*FIXME we fail the array type, but we have to let other fields be set.*/
6835 klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6839 if (eclass->enumtype)
6840 klass->cast_class = eclass->element_class;
6842 klass->cast_class = eclass;
6844 switch (klass->cast_class->byval_arg.type) {
6846 klass->cast_class = mono_defaults.byte_class;
6849 klass->cast_class = mono_defaults.int16_class;
6852 #if SIZEOF_VOID_P == 4
6856 klass->cast_class = mono_defaults.int32_class;
6859 #if SIZEOF_VOID_P == 8
6863 klass->cast_class = mono_defaults.int64_class;
6869 klass->element_class = eclass;
6871 if ((rank > 1) || bounded) {
6872 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6873 klass->byval_arg.type = MONO_TYPE_ARRAY;
6874 klass->byval_arg.data.array = at;
6875 at->eklass = eclass;
6877 /* FIXME: complete.... */
6879 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6880 klass->byval_arg.data.klass = eclass;
6882 klass->this_arg = klass->byval_arg;
6883 klass->this_arg.byref = 1;
6885 mono_loader_lock ();
6887 /* Check cache again */
6889 if (rank == 1 && !bounded) {
6890 mono_os_mutex_lock (&image->szarray_cache_lock);
6891 cached = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6892 mono_os_mutex_unlock (&image->szarray_cache_lock);
6894 rootlist = (GSList *)g_hash_table_lookup (image->array_cache, eclass);
6895 for (list = rootlist; list; list = list->next) {
6896 k = (MonoClass *)list->data;
6897 if ((k->rank == rank) && (k->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6904 mono_loader_unlock ();
6908 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6910 classes_size += sizeof (MonoClassArray);
6911 ++class_array_count;
6913 if (rank == 1 && !bounded) {
6914 mono_os_mutex_lock (&image->szarray_cache_lock);
6915 g_hash_table_insert (image->szarray_cache, eclass, klass);
6916 mono_os_mutex_unlock (&image->szarray_cache_lock);
6918 list = g_slist_append (rootlist, klass);
6919 g_hash_table_insert (image->array_cache, eclass, list);
6922 mono_loader_unlock ();
6924 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6930 * mono_array_class_get:
6931 * @element_class: element class
6932 * @rank: the dimension of the array class
6934 * Returns: A class object describing the array with element type @element_type and
6938 mono_array_class_get (MonoClass *eclass, guint32 rank)
6940 return mono_bounded_array_class_get (eclass, rank, FALSE);
6944 * mono_class_instance_size:
6947 * Use to get the size of a class in bytes.
6949 * Returns: The size of an object instance
6952 mono_class_instance_size (MonoClass *klass)
6954 if (!klass->size_inited)
6955 mono_class_init (klass);
6957 return klass->instance_size;
6961 * mono_class_min_align:
6964 * Use to get the computed minimum alignment requirements for the specified class.
6966 * Returns: minimum alignment requirements
6969 mono_class_min_align (MonoClass *klass)
6971 if (!klass->size_inited)
6972 mono_class_init (klass);
6974 return klass->min_align;
6978 * mono_class_value_size:
6981 * This function is used for value types, and return the
6982 * space and the alignment to store that kind of value object.
6984 * Returns: the size of a value of kind @klass
6987 mono_class_value_size (MonoClass *klass, guint32 *align)
6991 /* fixme: check disable, because we still have external revereces to
6992 * mscorlib and Dummy Objects
6994 /*g_assert (klass->valuetype);*/
6996 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6999 *align = klass->min_align;
7005 * mono_class_data_size:
7008 * Returns: The size of the static class data
7011 mono_class_data_size (MonoClass *klass)
7014 mono_class_init (klass);
7015 /* This can happen with dynamically created types */
7016 if (!klass->fields_inited)
7017 mono_class_setup_fields (klass);
7019 /* in arrays, sizes.class_size is unioned with element_size
7020 * and arrays have no static fields
7024 return klass->sizes.class_size;
7028 * Auxiliary routine to mono_class_get_field
7030 * Takes a field index instead of a field token.
7032 static MonoClassField *
7033 mono_class_get_field_idx (MonoClass *klass, int idx)
7035 mono_class_setup_fields (klass);
7036 if (mono_class_has_failure (klass))
7040 int first_field_idx = mono_class_get_first_field_idx (klass);
7041 int fcount = mono_class_get_field_count (klass);
7042 if (klass->image->uncompressed_metadata) {
7044 * first_field_idx points to the FieldPtr table, while idx points into the
7045 * Field table, so we have to do a search.
7047 /*FIXME this is broken for types with multiple fields with the same name.*/
7048 const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
7051 for (i = 0; i < fcount; ++i)
7052 if (mono_field_get_name (&klass->fields [i]) == name)
7053 return &klass->fields [i];
7054 g_assert_not_reached ();
7057 if ((idx >= first_field_idx) && (idx < first_field_idx + fcount)){
7058 return &klass->fields [idx - first_field_idx];
7062 klass = klass->parent;
7068 * mono_class_get_field:
7069 * @class: the class to lookup the field.
7070 * @field_token: the field token
7072 * Returns: A MonoClassField representing the type and offset of
7073 * the field, or a NULL value if the field does not belong to this
7077 mono_class_get_field (MonoClass *klass, guint32 field_token)
7079 int idx = mono_metadata_token_index (field_token);
7081 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
7083 return mono_class_get_field_idx (klass, idx - 1);
7087 * mono_class_get_field_from_name:
7088 * @klass: the class to lookup the field.
7089 * @name: the field name
7091 * Search the class @klass and it's parents for a field with the name @name.
7093 * Returns: The MonoClassField pointer of the named field or NULL
7096 mono_class_get_field_from_name (MonoClass *klass, const char *name)
7098 return mono_class_get_field_from_name_full (klass, name, NULL);
7102 * mono_class_get_field_from_name_full:
7103 * @klass: the class to lookup the field.
7104 * @name: the field name
7105 * @type: the type of the fields. This optional.
7107 * Search the class @klass and it's parents for a field with the name @name and type @type.
7109 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
7110 * of its generic type definition.
7112 * Returns: The MonoClassField pointer of the named field or NULL
7115 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
7119 mono_class_setup_fields (klass);
7120 if (mono_class_has_failure (klass))
7124 int fcount = mono_class_get_field_count (klass);
7125 for (i = 0; i < fcount; ++i) {
7126 MonoClassField *field = &klass->fields [i];
7128 if (strcmp (name, mono_field_get_name (field)) != 0)
7132 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
7133 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
7138 klass = klass->parent;
7144 * mono_class_get_field_token:
7145 * @field: the field we need the token of
7147 * Get the token of a field. Note that the tokesn is only valid for the image
7148 * the field was loaded from. Don't use this function for fields in dynamic types.
7150 * Returns: The token representing the field in the image it was loaded from.
7153 mono_class_get_field_token (MonoClassField *field)
7155 MonoClass *klass = field->parent;
7158 mono_class_setup_fields (klass);
7163 int first_field_idx = mono_class_get_first_field_idx (klass);
7164 int fcount = mono_class_get_field_count (klass);
7165 for (i = 0; i < fcount; ++i) {
7166 if (&klass->fields [i] == field) {
7167 int idx = first_field_idx + i + 1;
7169 if (klass->image->uncompressed_metadata)
7170 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
7171 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
7174 klass = klass->parent;
7177 g_assert_not_reached ();
7182 mono_field_get_index (MonoClassField *field)
7184 int index = field - field->parent->fields;
7185 g_assert (index >= 0 && index < mono_class_get_field_count (field->parent));
7191 * mono_class_get_field_default_value:
7193 * Return the default value of the field as a pointer into the metadata blob.
7196 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
7199 guint32 constant_cols [MONO_CONSTANT_SIZE];
7201 MonoClass *klass = field->parent;
7203 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7205 MonoClassExt *ext = mono_class_get_ext (klass);
7206 if (!ext || !ext->field_def_values) {
7207 MonoFieldDefaultValue *def_values;
7209 mono_class_alloc_ext (klass);
7210 ext = mono_class_get_ext (klass);
7212 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
7214 mono_image_lock (klass->image);
7215 mono_memory_barrier ();
7216 if (!ext->field_def_values)
7217 ext->field_def_values = def_values;
7218 mono_image_unlock (klass->image);
7221 field_index = mono_field_get_index (field);
7223 if (!ext->field_def_values [field_index].data) {
7224 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7228 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7230 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7231 ext->field_def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7232 ext->field_def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7235 *def_type = ext->field_def_values [field_index].def_type;
7236 return ext->field_def_values [field_index].data;
7240 mono_property_get_index (MonoProperty *prop)
7242 MonoClassExt *ext = mono_class_get_ext (prop->parent);
7243 int index = prop - ext->properties;
7245 g_assert (index >= 0 && index < ext->property.count);
7251 * mono_class_get_property_default_value:
7253 * Return the default value of the field as a pointer into the metadata blob.
7256 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7259 guint32 constant_cols [MONO_CONSTANT_SIZE];
7260 MonoClass *klass = property->parent;
7262 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7264 * We don't cache here because it is not used by C# so it's quite rare, but
7265 * we still do the lookup in klass->ext because that is where the data
7266 * is stored for dynamic assemblies.
7269 if (image_is_dynamic (klass->image)) {
7270 MonoClassExt *ext = mono_class_get_ext (klass);
7271 int prop_index = mono_property_get_index (property);
7272 if (ext->prop_def_values && ext->prop_def_values [prop_index].data) {
7273 *def_type = ext->prop_def_values [prop_index].def_type;
7274 return ext->prop_def_values [prop_index].data;
7278 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7282 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7283 *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7284 return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7288 mono_class_get_event_token (MonoEvent *event)
7290 MonoClass *klass = event->parent;
7294 MonoClassExt *ext = mono_class_get_ext (klass);
7296 for (i = 0; i < ext->event.count; ++i) {
7297 if (&ext->events [i] == event)
7298 return mono_metadata_make_token (MONO_TABLE_EVENT, ext->event.first + i + 1);
7301 klass = klass->parent;
7304 g_assert_not_reached ();
7309 * mono_class_get_property_from_name:
7311 * @name: name of the property to lookup in the specified class
7313 * Use this method to lookup a property in a class
7314 * Returns: the MonoProperty with the given name, or NULL if the property
7315 * does not exist on the @klass.
7318 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7322 gpointer iter = NULL;
7323 while ((p = mono_class_get_properties (klass, &iter))) {
7324 if (! strcmp (name, p->name))
7327 klass = klass->parent;
7333 * mono_class_get_property_token:
7334 * @prop: MonoProperty to query
7336 * Returns: The ECMA token for the specified property.
7339 mono_class_get_property_token (MonoProperty *prop)
7341 MonoClass *klass = prop->parent;
7345 gpointer iter = NULL;
7346 MonoClassExt *ext = mono_class_get_ext (klass);
7347 while ((p = mono_class_get_properties (klass, &iter))) {
7348 if (&ext->properties [i] == prop)
7349 return mono_metadata_make_token (MONO_TABLE_PROPERTY, ext->property.first + i + 1);
7353 klass = klass->parent;
7356 g_assert_not_reached ();
7361 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7363 const char *name, *nspace;
7364 if (image_is_dynamic (image))
7365 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7367 switch (type_token & 0xff000000){
7368 case MONO_TOKEN_TYPE_DEF: {
7369 guint32 cols [MONO_TYPEDEF_SIZE];
7370 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7371 guint tidx = mono_metadata_token_index (type_token);
7373 if (tidx > tt->rows)
7374 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7376 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7377 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7378 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7379 if (strlen (nspace) == 0)
7380 return g_strdup_printf ("%s", name);
7382 return g_strdup_printf ("%s.%s", nspace, name);
7385 case MONO_TOKEN_TYPE_REF: {
7387 guint32 cols [MONO_TYPEREF_SIZE];
7388 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7389 guint tidx = mono_metadata_token_index (type_token);
7392 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7394 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7395 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7396 mono_error_cleanup (&error);
7400 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7401 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7402 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7403 if (strlen (nspace) == 0)
7404 return g_strdup_printf ("%s", name);
7406 return g_strdup_printf ("%s.%s", nspace, name);
7409 case MONO_TOKEN_TYPE_SPEC:
7410 return g_strdup_printf ("Typespec 0x%08x", type_token);
7412 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7417 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7419 if (image_is_dynamic (image))
7420 return g_strdup_printf ("DynamicAssembly %s", image->name);
7422 switch (type_token & 0xff000000){
7423 case MONO_TOKEN_TYPE_DEF:
7424 if (image->assembly)
7425 return mono_stringify_assembly_name (&image->assembly->aname);
7426 else if (image->assembly_name)
7427 return g_strdup (image->assembly_name);
7428 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7429 case MONO_TOKEN_TYPE_REF: {
7431 MonoAssemblyName aname;
7432 guint32 cols [MONO_TYPEREF_SIZE];
7433 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7434 guint32 idx = mono_metadata_token_index (type_token);
7437 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7439 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7440 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7441 mono_error_cleanup (&error);
7444 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7446 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7447 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7448 case MONO_RESOLUTION_SCOPE_MODULE:
7450 return g_strdup ("");
7451 case MONO_RESOLUTION_SCOPE_MODULEREF:
7453 return g_strdup ("");
7454 case MONO_RESOLUTION_SCOPE_TYPEREF:
7456 return g_strdup ("");
7457 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7458 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7459 return mono_stringify_assembly_name (&aname);
7461 g_assert_not_reached ();
7465 case MONO_TOKEN_TYPE_SPEC:
7467 return g_strdup ("");
7469 g_assert_not_reached ();
7476 * mono_class_get_full:
7477 * @image: the image where the class resides
7478 * @type_token: the token for the class
7479 * @context: the generic context used to evaluate generic instantiations in
7480 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7482 * Returns: The MonoClass that represents @type_token in @image
7485 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7489 klass = mono_class_get_checked (image, type_token, &error);
7491 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7492 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7494 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7500 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7504 mono_error_init (error);
7505 klass = mono_class_get_checked (image, type_token, error);
7507 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7508 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7513 * mono_class_get_checked:
7514 * @image: the image where the class resides
7515 * @type_token: the token for the class
7516 * @error: error object to return any error
7518 * Returns: The MonoClass that represents @type_token in @image, or NULL on error.
7521 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7523 MonoClass *klass = NULL;
7525 mono_error_init (error);
7527 if (image_is_dynamic (image)) {
7528 int table = mono_metadata_token_table (type_token);
7530 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7531 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7534 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
7538 switch (type_token & 0xff000000){
7539 case MONO_TOKEN_TYPE_DEF:
7540 klass = mono_class_create_from_typedef (image, type_token, error);
7542 case MONO_TOKEN_TYPE_REF:
7543 klass = mono_class_from_typeref_checked (image, type_token, error);
7545 case MONO_TOKEN_TYPE_SPEC:
7546 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7549 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7553 /* Generic case, should be avoided for when a better error is possible. */
7554 if (!klass && mono_error_ok (error)) {
7555 char *name = mono_class_name_from_token (image, type_token);
7556 char *assembly = mono_assembly_name_from_token (image, type_token);
7557 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7565 * mono_type_get_checked:
7566 * @image: the image where the type resides
7567 * @type_token: the token for the type
7568 * @context: the generic context used to evaluate generic instantiations in
7569 * @error: Error handling context
7571 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7573 * Returns: The MonoType that represents @type_token in @image
7576 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7578 MonoType *type = NULL;
7579 gboolean inflated = FALSE;
7581 mono_error_init (error);
7583 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7584 if (image_is_dynamic (image)) {
7585 MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
7586 return_val_if_nok (error, NULL);
7587 return mono_class_get_type (klass);
7590 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7591 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7598 return mono_class_get_type (klass);
7601 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7608 MonoType *tmp = type;
7609 type = mono_class_get_type (mono_class_from_mono_type (type));
7610 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7611 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7612 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7614 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7616 if (type->type != tmp->type)
7619 mono_metadata_free_type (tmp);
7626 * @image: image where the class token will be looked up.
7627 * @type_token: a type token from the image
7629 * Returns the MonoClass with the given @type_token on the @image
7632 mono_class_get (MonoImage *image, guint32 type_token)
7634 return mono_class_get_full (image, type_token, NULL);
7638 * mono_image_init_name_cache:
7640 * Initializes the class name cache stored in image->name_cache.
7642 * LOCKING: Acquires the corresponding image lock.
7645 mono_image_init_name_cache (MonoImage *image)
7647 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7648 guint32 cols [MONO_TYPEDEF_SIZE];
7651 guint32 i, visib, nspace_index;
7652 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7654 if (image->name_cache)
7657 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7659 if (image_is_dynamic (image)) {
7660 mono_image_lock (image);
7661 if (image->name_cache) {
7662 /* Somebody initialized it before us */
7663 g_hash_table_destroy (the_name_cache);
7665 mono_atomic_store_release (&image->name_cache, the_name_cache);
7667 mono_image_unlock (image);
7671 /* Temporary hash table to avoid lookups in the nspace_table */
7672 name_cache2 = g_hash_table_new (NULL, NULL);
7674 for (i = 1; i <= t->rows; ++i) {
7675 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7676 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7678 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7679 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7681 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7683 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7684 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7686 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7687 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7688 if (!nspace_table) {
7689 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7690 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7691 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7694 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7697 /* Load type names from EXPORTEDTYPES table */
7699 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7700 guint32 cols [MONO_EXP_TYPE_SIZE];
7703 for (i = 0; i < t->rows; ++i) {
7704 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7706 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7707 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7711 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7712 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7714 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7715 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7716 if (!nspace_table) {
7717 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7718 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7719 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7722 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7726 g_hash_table_destroy (name_cache2);
7728 mono_image_lock (image);
7729 if (image->name_cache) {
7730 /* Somebody initialized it before us */
7731 g_hash_table_destroy (the_name_cache);
7733 mono_atomic_store_release (&image->name_cache, the_name_cache);
7735 mono_image_unlock (image);
7738 /*FIXME Only dynamic assemblies should allow this operation.*/
7740 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7741 const char *name, guint32 index)
7743 GHashTable *nspace_table;
7744 GHashTable *name_cache;
7747 mono_image_init_name_cache (image);
7748 mono_image_lock (image);
7750 name_cache = image->name_cache;
7751 if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7752 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7753 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7756 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7757 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7759 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7761 mono_image_unlock (image);
7770 find_nocase (gpointer key, gpointer value, gpointer user_data)
7772 char *name = (char*)key;
7773 FindUserData *data = (FindUserData*)user_data;
7775 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7776 data->value = value;
7780 * mono_class_from_name_case:
7781 * @image: The MonoImage where the type is looked up in
7782 * @name_space: the type namespace
7783 * @name: the type short name.
7784 * @deprecated: use the mono_class_from_name_case_checked variant instead.
7786 * Obtains a MonoClass with a given namespace and a given name which
7787 * is located in the given MonoImage. The namespace and name
7788 * lookups are case insensitive.
7791 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7794 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7795 mono_error_cleanup (&error);
7801 * mono_class_from_name_case:
7802 * @image: The MonoImage where the type is looked up in
7803 * @name_space: the type namespace
7804 * @name: the type short name.
7807 * Obtains a MonoClass with a given namespace and a given name which
7808 * is located in the given MonoImage. The namespace and name
7809 * lookups are case insensitive.
7811 * Returns: The MonoClass if the given namespace and name were found, or NULL if it
7812 * was not found. The @error object will contain information about the problem
7816 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7818 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7819 guint32 cols [MONO_TYPEDEF_SIZE];
7824 mono_error_init (error);
7826 if (image_is_dynamic (image)) {
7828 FindUserData user_data;
7830 mono_image_init_name_cache (image);
7831 mono_image_lock (image);
7833 user_data.key = name_space;
7834 user_data.value = NULL;
7835 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7837 if (user_data.value) {
7838 GHashTable *nspace_table = (GHashTable*)user_data.value;
7840 user_data.key = name;
7841 user_data.value = NULL;
7843 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7845 if (user_data.value)
7846 token = GPOINTER_TO_UINT (user_data.value);
7849 mono_image_unlock (image);
7852 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7858 /* add a cache if needed */
7859 for (i = 1; i <= t->rows; ++i) {
7860 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7861 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7863 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7864 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7866 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7868 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7869 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7870 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7871 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7877 return_nested_in (MonoClass *klass, char *nested)
7880 char *s = strchr (nested, '/');
7881 gpointer iter = NULL;
7888 while ((found = mono_class_get_nested_types (klass, &iter))) {
7889 if (strcmp (found->name, nested) == 0) {
7891 return return_nested_in (found, s);
7899 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7901 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7902 MonoImage *file_image;
7906 mono_error_init (error);
7909 * The EXPORTEDTYPES table only contains public types, so have to search the
7911 * Note: image->modules contains the contents of the MODULEREF table, while
7912 * the real module list is in the FILE table.
7914 for (i = 0; i < file_table->rows; i++) {
7915 guint32 cols [MONO_FILE_SIZE];
7916 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7917 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7920 file_image = mono_image_load_file_for_image_checked (image, i + 1, error);
7922 klass = mono_class_from_name_checked (file_image, name_space, name, error);
7923 if (klass || !is_ok (error))
7932 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7934 GHashTable *nspace_table;
7935 MonoImage *loaded_image;
7942 mono_error_init (error);
7944 // Checking visited images avoids stack overflows when cyclic references exist.
7945 if (g_hash_table_lookup (visited_images, image))
7948 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7950 if ((nested = strchr (name, '/'))) {
7951 int pos = nested - name;
7952 int len = strlen (name);
7955 memcpy (buf, name, len + 1);
7957 nested = buf + pos + 1;
7961 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7962 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7963 gboolean res = get_class_from_name (image, name_space, name, &klass);
7966 klass = search_modules (image, name_space, name, error);
7971 return klass ? return_nested_in (klass, nested) : NULL;
7977 mono_image_init_name_cache (image);
7978 mono_image_lock (image);
7980 nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7983 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7985 mono_image_unlock (image);
7987 if (!token && image_is_dynamic (image) && image->modules) {
7988 /* Search modules as well */
7989 for (i = 0; i < image->module_count; ++i) {
7990 MonoImage *module = image->modules [i];
7992 klass = mono_class_from_name_checked (module, name_space, name, error);
7993 if (klass || !is_ok (error))
7999 klass = search_modules (image, name_space, name, error);
8000 if (klass || !is_ok (error))
8005 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
8006 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
8007 guint32 cols [MONO_EXP_TYPE_SIZE];
8010 idx = mono_metadata_token_index (token);
8012 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
8014 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
8015 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
8016 loaded_image = mono_assembly_load_module_checked (image->assembly, impl >> MONO_IMPLEMENTATION_BITS, error);
8019 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
8021 return klass ? return_nested_in (klass, nested) : NULL;
8023 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
8024 guint32 assembly_idx;
8026 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
8028 mono_assembly_load_reference (image, assembly_idx - 1);
8029 g_assert (image->references [assembly_idx - 1]);
8030 if (image->references [assembly_idx - 1] == (gpointer)-1)
8032 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
8034 return klass ? return_nested_in (klass, nested) : NULL;
8037 g_assert_not_reached ();
8041 token = MONO_TOKEN_TYPE_DEF | token;
8043 klass = mono_class_get_checked (image, token, error);
8045 return return_nested_in (klass, nested);
8050 * mono_class_from_name_checked:
8051 * @image: The MonoImage where the type is looked up in
8052 * @name_space: the type namespace
8053 * @name: the type short name.
8055 * Obtains a MonoClass with a given namespace and a given name which
8056 * is located in the given MonoImage.
8058 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
8059 * set if the class was not found or it will return NULL and set the error if there was a loading error.
8062 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
8065 GHashTable *visited_images;
8067 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
8069 klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
8071 g_hash_table_destroy (visited_images);
8077 * mono_class_from_name:
8078 * @image: The MonoImage where the type is looked up in
8079 * @name_space: the type namespace
8080 * @name: the type short name.
8082 * Obtains a MonoClass with a given namespace and a given name which
8083 * is located in the given MonoImage.
8085 * To reference nested classes, use the "/" character as a separator.
8086 * For example use "Foo/Bar" to reference the class Bar that is nested
8087 * inside Foo, like this: "class Foo { class Bar {} }".
8090 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
8095 klass = mono_class_from_name_checked (image, name_space, name, &error);
8096 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
8102 * mono_class_load_from_name:
8103 * @image: The MonoImage where the type is looked up in
8104 * @name_space: the type namespace
8105 * @name: the type short name.
8107 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
8108 * This function should be used by the runtime for critical types to which there's no way to recover but crash
8109 * If they are missing. Thing of System.Object or System.String.
8112 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
8117 klass = mono_class_from_name_checked (image, name_space, name, &error);
8119 g_error ("Runtime critical type %s.%s not found", name_space, name);
8120 if (!mono_error_ok (&error))
8121 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8126 * mono_class_try_load_from_name:
8127 * @image: The MonoImage where the type is looked up in
8128 * @name_space: the type namespace
8129 * @name: the type short name.
8131 * This function tries to load a type, returning the class was found or NULL otherwise.
8132 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
8134 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
8135 * a type that we would otherwise assume to be available but was not due some error.
8139 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
8144 klass = mono_class_from_name_checked (image, name_space, name, &error);
8145 if (!mono_error_ok (&error))
8146 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8152 * mono_class_is_subclass_of:
8153 * @klass: class to probe if it is a subclass of another one
8154 * @klassc: the class we suspect is the base class
8155 * @check_interfaces: whether we should perform interface checks
8157 * This method determines whether @klass is a subclass of @klassc.
8159 * If the @check_interfaces flag is set, then if @klassc is an interface
8160 * this method return TRUE if the @klass implements the interface or
8161 * if @klass is an interface, if one of its base classes is @klass.
8163 * If @check_interfaces is false then, then if @klass is not an interface
8164 * then it returns TRUE if the @klass is a subclass of @klassc.
8166 * if @klass is an interface and @klassc is System.Object, then this function
8171 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
8172 gboolean check_interfaces)
8174 /* FIXME test for interfaces with variant generic arguments */
8175 mono_class_init (klass);
8176 mono_class_init (klassc);
8178 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
8179 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
8181 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
8184 for (i = 0; i < klass->interface_count; i ++) {
8185 MonoClass *ic = klass->interfaces [i];
8190 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
8195 * MS.NET thinks interfaces are a subclass of Object, so we think it as
8198 if (klassc == mono_defaults.object_class)
8205 mono_type_is_generic_argument (MonoType *type)
8207 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
8211 mono_class_has_variant_generic_params (MonoClass *klass)
8214 MonoGenericContainer *container;
8216 if (!mono_class_is_ginst (klass))
8219 container = mono_class_get_generic_container (mono_class_get_generic_class (klass)->container_class);
8221 for (i = 0; i < container->type_argc; ++i)
8222 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8229 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8231 if (target == candidate)
8234 if (check_for_reference_conv &&
8235 mono_type_is_generic_argument (&target->byval_arg) &&
8236 mono_type_is_generic_argument (&candidate->byval_arg)) {
8237 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8238 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8240 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8243 if (!mono_class_is_assignable_from (target, candidate))
8249 * @container the generic container from the GTD
8250 * @klass: the class to be assigned to
8251 * @oklass: the source class
8253 * Both @klass and @oklass must be instances of the same generic interface.
8255 * Returns: TRUE if @klass can be assigned to a @klass variable
8258 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8261 MonoType **klass_argv, **oklass_argv;
8262 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8263 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8265 if (klass == oklass)
8268 /*Viable candidates are instances of the same generic interface*/
8269 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8272 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8273 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8275 for (j = 0; j < container->type_argc; ++j) {
8276 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8277 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8279 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8283 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8284 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8286 if (param1_class != param2_class) {
8287 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8288 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8290 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8291 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8301 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8303 MonoGenericParam *gparam, *ogparam;
8304 MonoGenericParamInfo *tinfo, *cinfo;
8305 MonoClass **candidate_class;
8306 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8309 if (target == candidate)
8311 if (target->byval_arg.type != candidate->byval_arg.type)
8314 gparam = target->byval_arg.data.generic_param;
8315 ogparam = candidate->byval_arg.data.generic_param;
8316 tinfo = mono_generic_param_info (gparam);
8317 cinfo = mono_generic_param_info (ogparam);
8319 class_constraint_satisfied = FALSE;
8320 valuetype_constraint_satisfied = FALSE;
8322 /*candidate must have a super set of target's special constraints*/
8323 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8324 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8326 if (cinfo->constraints) {
8327 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8328 MonoClass *cc = *candidate_class;
8330 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8331 class_constraint_satisfied = TRUE;
8332 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8333 valuetype_constraint_satisfied = TRUE;
8336 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8337 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8339 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8341 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8343 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8344 valuetype_constraint_satisfied)) {
8349 /*candidate type constraints must be a superset of target's*/
8350 if (tinfo->constraints) {
8351 MonoClass **target_class;
8352 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8353 MonoClass *tc = *target_class;
8356 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8357 * check it's constraints since it satisfy the constraint by itself.
8359 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8362 if (!cinfo->constraints)
8365 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8366 MonoClass *cc = *candidate_class;
8368 if (mono_class_is_assignable_from (tc, cc))
8372 * This happens when we have the following:
8374 * Bar<K> where K : IFace
8375 * Foo<T, U> where T : U where U : IFace
8377 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8380 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8381 if (mono_gparam_is_assignable_from (target, cc))
8385 if (!*candidate_class)
8390 /*candidate itself must have a constraint that satisfy target*/
8391 if (cinfo->constraints) {
8392 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8393 MonoClass *cc = *candidate_class;
8394 if (mono_class_is_assignable_from (target, cc))
8402 * mono_class_is_assignable_from:
8403 * @klass: the class to be assigned to
8404 * @oklass: the source class
8406 * Returns: TRUE if an instance of object oklass can be assigned to an
8407 * instance of object @klass
8410 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8413 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8415 mono_class_init (klass);
8417 if (!oklass->inited)
8418 mono_class_init (oklass);
8420 if (mono_class_has_failure (klass) || mono_class_has_failure (oklass))
8423 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8424 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8426 return mono_gparam_is_assignable_from (klass, oklass);
8429 if (MONO_CLASS_IS_INTERFACE (klass)) {
8430 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8431 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8432 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8436 for (i = 0; constraints [i]; ++i) {
8437 if (mono_class_is_assignable_from (klass, constraints [i]))
8445 /* interface_offsets might not be set for dynamic classes */
8446 if (mono_class_get_ref_info_handle (oklass) && !oklass->interface_bitmap) {
8448 * oklass might be a generic type parameter but they have
8449 * interface_offsets set.
8451 gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8452 if (!is_ok (&error)) {
8453 mono_error_cleanup (&error);
8458 if (!oklass->interface_bitmap)
8459 /* Happens with generic instances of not-yet created dynamic types */
8461 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8464 if (mono_class_has_variant_generic_params (klass)) {
8466 mono_class_setup_interfaces (oklass, &error);
8467 if (!mono_error_ok (&error)) {
8468 mono_error_cleanup (&error);
8472 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8473 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8474 MonoClass *iface = oklass->interfaces_packed [i];
8476 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8481 } else if (klass->delegate) {
8482 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8484 }else if (klass->rank) {
8485 MonoClass *eclass, *eoclass;
8487 if (oklass->rank != klass->rank)
8490 /* vectors vs. one dimensional arrays */
8491 if (oklass->byval_arg.type != klass->byval_arg.type)
8494 eclass = klass->cast_class;
8495 eoclass = oklass->cast_class;
8498 * a is b does not imply a[] is b[] when a is a valuetype, and
8499 * b is a reference type.
8502 if (eoclass->valuetype) {
8503 if ((eclass == mono_defaults.enum_class) ||
8504 (eclass == mono_defaults.enum_class->parent) ||
8505 (eclass == mono_defaults.object_class))
8509 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8510 } else if (mono_class_is_nullable (klass)) {
8511 if (mono_class_is_nullable (oklass))
8512 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8514 return mono_class_is_assignable_from (klass->cast_class, oklass);
8515 } else if (klass == mono_defaults.object_class)
8518 return mono_class_has_parent (oklass, klass);
8521 /*Check if @oklass is variant compatible with @klass.*/
8523 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8526 MonoType **klass_argv, **oklass_argv;
8527 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8528 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8530 /*Viable candidates are instances of the same generic interface*/
8531 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8534 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8535 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8537 for (j = 0; j < container->type_argc; ++j) {
8538 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8539 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8541 if (param1_class->valuetype != param2_class->valuetype)
8545 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8546 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8548 if (param1_class != param2_class) {
8549 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8550 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8552 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8553 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8561 /*Check if @candidate implements the interface @target*/
8563 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8567 gboolean is_variant = mono_class_has_variant_generic_params (target);
8569 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8570 if (mono_class_is_variant_compatible_slow (target, candidate))
8575 if (candidate == target)
8578 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8579 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8580 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (candidate);
8582 if (tb && tb->interfaces) {
8583 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8584 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8585 MonoClass *iface_class;
8587 /* we can't realize the type here since it can do pretty much anything. */
8590 iface_class = mono_class_from_mono_type (iface->type);
8591 if (iface_class == target)
8593 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8595 if (mono_class_implement_interface_slow (target, iface_class))
8600 /*setup_interfaces don't mono_class_init anything*/
8601 /*FIXME this doesn't handle primitive type arrays.
8602 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8603 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8605 mono_class_setup_interfaces (candidate, &error);
8606 if (!mono_error_ok (&error)) {
8607 mono_error_cleanup (&error);
8611 for (i = 0; i < candidate->interface_count; ++i) {
8612 if (candidate->interfaces [i] == target)
8615 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8618 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8622 candidate = candidate->parent;
8623 } while (candidate);
8629 * Check if @oklass can be assigned to @klass.
8630 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8633 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8635 if (candidate == target)
8637 if (target == mono_defaults.object_class)
8640 if (mono_class_has_parent (candidate, target))
8643 /*If target is not an interface there is no need to check them.*/
8644 if (MONO_CLASS_IS_INTERFACE (target))
8645 return mono_class_implement_interface_slow (target, candidate);
8647 if (target->delegate && mono_class_has_variant_generic_params (target))
8648 return mono_class_is_variant_compatible (target, candidate, FALSE);
8651 MonoClass *eclass, *eoclass;
8653 if (target->rank != candidate->rank)
8656 /* vectors vs. one dimensional arrays */
8657 if (target->byval_arg.type != candidate->byval_arg.type)
8660 eclass = target->cast_class;
8661 eoclass = candidate->cast_class;
8664 * a is b does not imply a[] is b[] when a is a valuetype, and
8665 * b is a reference type.
8668 if (eoclass->valuetype) {
8669 if ((eclass == mono_defaults.enum_class) ||
8670 (eclass == mono_defaults.enum_class->parent) ||
8671 (eclass == mono_defaults.object_class))
8675 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8677 /*FIXME properly handle nullables */
8678 /*FIXME properly handle (M)VAR */
8683 * mono_class_get_cctor:
8684 * @klass: A MonoClass pointer
8686 * Returns: The static constructor of @klass if it exists, NULL otherwise.
8689 mono_class_get_cctor (MonoClass *klass)
8691 MonoCachedClassInfo cached_info;
8693 if (image_is_dynamic (klass->image)) {
8695 * has_cctor is not set for these classes because mono_class_init () is
8698 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8701 if (!klass->has_cctor)
8704 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8706 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8707 if (!mono_error_ok (&error))
8708 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8712 if (mono_class_is_ginst (klass) && !klass->methods)
8713 return mono_class_get_inflated_method (klass, mono_class_get_cctor (mono_class_get_generic_class (klass)->container_class));
8715 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8719 * mono_class_get_finalizer:
8720 * @klass: The MonoClass pointer
8722 * Returns: The finalizer method of @klass if it exists, NULL otherwise.
8725 mono_class_get_finalizer (MonoClass *klass)
8727 MonoCachedClassInfo cached_info;
8730 mono_class_init (klass);
8731 if (!mono_class_has_finalizer (klass))
8734 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8736 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8737 if (!mono_error_ok (&error))
8738 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8741 mono_class_setup_vtable (klass);
8742 return klass->vtable [finalize_slot];
8747 * mono_class_needs_cctor_run:
8748 * @klass: the MonoClass pointer
8749 * @caller: a MonoMethod describing the caller
8751 * Determines whenever the class has a static constructor and whenever it
8752 * needs to be called when executing CALLER.
8755 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8759 method = mono_class_get_cctor (klass);
8761 return (method == caller) ? FALSE : TRUE;
8767 * mono_class_array_element_size:
8770 * Returns: The number of bytes an element of type @klass
8771 * uses when stored into an array.
8774 mono_class_array_element_size (MonoClass *klass)
8776 MonoType *type = &klass->byval_arg;
8779 switch (type->type) {
8782 case MONO_TYPE_BOOLEAN:
8786 case MONO_TYPE_CHAR:
8795 case MONO_TYPE_CLASS:
8796 case MONO_TYPE_STRING:
8797 case MONO_TYPE_OBJECT:
8798 case MONO_TYPE_SZARRAY:
8799 case MONO_TYPE_ARRAY:
8800 return sizeof (gpointer);
8805 case MONO_TYPE_VALUETYPE:
8806 if (type->data.klass->enumtype) {
8807 type = mono_class_enum_basetype (type->data.klass);
8808 klass = klass->element_class;
8811 return mono_class_instance_size (klass) - sizeof (MonoObject);
8812 case MONO_TYPE_GENERICINST:
8813 type = &type->data.generic_class->container_class->byval_arg;
8816 case MONO_TYPE_MVAR: {
8819 return mono_type_size (type, &align);
8821 case MONO_TYPE_VOID:
8825 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8831 * mono_array_element_size:
8832 * @ac: pointer to a #MonoArrayClass
8834 * Returns: The size of single array element.
8837 mono_array_element_size (MonoClass *ac)
8839 g_assert (ac->rank);
8840 return ac->sizes.element_size;
8844 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8845 MonoGenericContext *context)
8848 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8849 g_assert (mono_error_ok (&error));
8854 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8855 MonoGenericContext *context, MonoError *error)
8857 mono_error_init (error);
8859 if (image_is_dynamic (image)) {
8860 MonoClass *tmp_handle_class;
8861 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
8863 mono_error_assert_ok (error);
8864 g_assert (tmp_handle_class);
8866 *handle_class = tmp_handle_class;
8868 if (tmp_handle_class == mono_defaults.typehandle_class)
8869 return &((MonoClass*)obj)->byval_arg;
8874 switch (token & 0xff000000) {
8875 case MONO_TOKEN_TYPE_DEF:
8876 case MONO_TOKEN_TYPE_REF:
8877 case MONO_TOKEN_TYPE_SPEC: {
8880 *handle_class = mono_defaults.typehandle_class;
8881 type = mono_type_get_checked (image, token, context, error);
8885 mono_class_init (mono_class_from_mono_type (type));
8886 /* We return a MonoType* as handle */
8889 case MONO_TOKEN_FIELD_DEF: {
8891 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8893 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8897 *handle_class = mono_defaults.fieldhandle_class;
8898 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8902 mono_class_init (klass);
8903 return mono_class_get_field (klass, token);
8905 case MONO_TOKEN_METHOD_DEF:
8906 case MONO_TOKEN_METHOD_SPEC: {
8908 meth = mono_get_method_checked (image, token, NULL, context, error);
8910 *handle_class = mono_defaults.methodhandle_class;
8916 case MONO_TOKEN_MEMBER_REF: {
8917 guint32 cols [MONO_MEMBERREF_SIZE];
8919 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8920 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8921 mono_metadata_decode_blob_size (sig, &sig);
8922 if (*sig == 0x6) { /* it's a field */
8924 MonoClassField *field;
8925 field = mono_field_from_token_checked (image, token, &klass, context, error);
8927 *handle_class = mono_defaults.fieldhandle_class;
8931 meth = mono_get_method_checked (image, token, NULL, context, error);
8933 *handle_class = mono_defaults.methodhandle_class;
8938 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8944 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
8946 MonoClass *handle_class;
8947 mono_error_init (error);
8948 return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
8952 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
8954 return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
8957 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8960 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8962 get_cached_class_info = func;
8966 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8968 if (!get_cached_class_info)
8971 return get_cached_class_info (klass, res);
8975 mono_install_get_class_from_name (MonoGetClassFromName func)
8977 get_class_from_name = func;
8981 * mono_class_get_image:
8983 * Use this method to get the `MonoImage*` where this class came from.
8985 * Returns: The image where this class is defined.
8988 mono_class_get_image (MonoClass *klass)
8990 return klass->image;
8994 * mono_class_get_element_class:
8995 * @klass: the MonoClass to act on
8997 * Use this function to get the element class of an array.
8999 * Returns: The element class of an array.
9002 mono_class_get_element_class (MonoClass *klass)
9004 return klass->element_class;
9008 * mono_class_is_valuetype:
9009 * @klass: the MonoClass to act on
9011 * Use this method to determine if the provided `MonoClass*` represents a value type,
9012 * or a reference type.
9014 * Returns: TRUE if the MonoClass represents a ValueType, FALSE if it represents a reference type.
9017 mono_class_is_valuetype (MonoClass *klass)
9019 return klass->valuetype;
9023 * mono_class_is_enum:
9024 * @klass: the MonoClass to act on
9026 * Use this function to determine if the provided `MonoClass*` represents an enumeration.
9028 * Returns: TRUE if the MonoClass represents an enumeration.
9031 mono_class_is_enum (MonoClass *klass)
9033 return klass->enumtype;
9037 * mono_class_enum_basetype:
9038 * @klass: the MonoClass to act on
9040 * Use this function to get the underlying type for an enumeration value.
9042 * Returns: The underlying type representation for an enumeration.
9045 mono_class_enum_basetype (MonoClass *klass)
9047 if (klass->element_class == klass)
9048 /* SRE or broken types */
9051 return &klass->element_class->byval_arg;
9055 * mono_class_get_parent
9056 * @klass: the MonoClass to act on
9058 * Returns: The parent class for this class.
9061 mono_class_get_parent (MonoClass *klass)
9063 return klass->parent;
9067 * mono_class_get_nesting_type:
9068 * @klass: the MonoClass to act on
9070 * Use this function to obtain the class that the provided `MonoClass*` is nested on.
9072 * If the return is NULL, this indicates that this class is not nested.
9074 * Returns: The container type where this type is nested or NULL if this type is not a nested type.
9077 mono_class_get_nesting_type (MonoClass *klass)
9079 return klass->nested_in;
9083 * mono_class_get_rank:
9084 * @klass: the MonoClass to act on
9086 * Returns: The rank for the array (the number of dimensions).
9089 mono_class_get_rank (MonoClass *klass)
9095 * mono_class_get_name
9096 * @klass: the MonoClass to act on
9098 * Returns: The name of the class.
9101 mono_class_get_name (MonoClass *klass)
9107 * mono_class_get_namespace:
9108 * @klass: the MonoClass to act on
9110 * Returns: The namespace of the class.
9113 mono_class_get_namespace (MonoClass *klass)
9115 return klass->name_space;
9119 * mono_class_get_type:
9120 * @klass: the MonoClass to act on
9122 * This method returns the internal Type representation for the class.
9124 * Returns: The MonoType from the class.
9127 mono_class_get_type (MonoClass *klass)
9129 return &klass->byval_arg;
9133 * mono_class_get_type_token:
9134 * @klass: the MonoClass to act on
9136 * This method returns type token for the class.
9138 * Returns: The type token for the class.
9141 mono_class_get_type_token (MonoClass *klass)
9143 return klass->type_token;
9147 * mono_class_get_byref_type:
9148 * @klass: the MonoClass to act on
9153 mono_class_get_byref_type (MonoClass *klass)
9155 return &klass->this_arg;
9159 * mono_class_num_fields:
9160 * @klass: the MonoClass to act on
9162 * Returns: The number of static and instance fields in the class.
9165 mono_class_num_fields (MonoClass *klass)
9167 return mono_class_get_field_count (klass);
9171 * mono_class_num_methods:
9172 * @klass: the MonoClass to act on
9174 * Returns: The number of methods in the class.
9177 mono_class_num_methods (MonoClass *klass)
9179 return mono_class_get_method_count (klass);
9183 * mono_class_num_properties
9184 * @klass: the MonoClass to act on
9186 * Returns: The number of properties in the class.
9189 mono_class_num_properties (MonoClass *klass)
9191 mono_class_setup_properties (klass);
9193 return mono_class_get_ext (klass)->property.count;
9197 * mono_class_num_events:
9198 * @klass: the MonoClass to act on
9200 * Returns: The number of events in the class.
9203 mono_class_num_events (MonoClass *klass)
9205 mono_class_setup_events (klass);
9207 return mono_class_get_ext (klass)->event.count;
9211 * mono_class_get_fields:
9212 * @klass: the MonoClass to act on
9214 * This routine is an iterator routine for retrieving the fields in a class.
9216 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9217 * iterate over all of the elements. When no more values are
9218 * available, the return value is NULL.
9220 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
9223 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9225 MonoClassField* field;
9229 mono_class_setup_fields (klass);
9230 if (mono_class_has_failure (klass))
9232 /* start from the first */
9233 if (mono_class_get_field_count (klass)) {
9234 *iter = &klass->fields [0];
9235 return &klass->fields [0];
9241 field = (MonoClassField *)*iter;
9243 if (field < &klass->fields [mono_class_get_field_count (klass)]) {
9251 * mono_class_get_methods
9252 * @klass: the MonoClass to act on
9254 * This routine is an iterator routine for retrieving the fields in a class.
9256 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9257 * iterate over all of the elements. When no more values are
9258 * available, the return value is NULL.
9260 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
9263 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9265 MonoMethod** method;
9269 mono_class_setup_methods (klass);
9272 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9273 * FIXME we should better report this error to the caller
9275 if (!klass->methods)
9277 /* start from the first */
9278 if (mono_class_get_method_count (klass)) {
9279 *iter = &klass->methods [0];
9280 return klass->methods [0];
9286 method = (MonoMethod **)*iter;
9288 if (method < &klass->methods [mono_class_get_method_count (klass)]) {
9296 * mono_class_get_virtual_methods:
9298 * Iterate over the virtual methods of KLASS.
9300 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9303 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9305 MonoMethod** method;
9308 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9310 mono_class_setup_methods (klass);
9312 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9313 * FIXME we should better report this error to the caller
9315 if (!klass->methods)
9317 /* start from the first */
9318 method = &klass->methods [0];
9320 method = (MonoMethod **)*iter;
9323 int mcount = mono_class_get_method_count (klass);
9324 while (method < &klass->methods [mcount]) {
9325 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9329 if (method < &klass->methods [mcount]) {
9336 /* Search directly in metadata to avoid calling setup_methods () */
9337 MonoMethod *res = NULL;
9343 start_index = GPOINTER_TO_UINT (*iter);
9346 int first_idx = mono_class_get_first_method_idx (klass);
9347 int mcount = mono_class_get_method_count (klass);
9348 for (i = start_index; i < mcount; ++i) {
9351 /* first_idx points into the methodptr table */
9352 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
9354 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9360 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9361 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9363 /* Add 1 here so the if (*iter) check fails */
9364 *iter = GUINT_TO_POINTER (i + 1);
9373 * mono_class_get_properties:
9374 * @klass: the MonoClass to act on
9376 * This routine is an iterator routine for retrieving the properties in a class.
9378 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9379 * iterate over all of the elements. When no more values are
9380 * available, the return value is NULL.
9382 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9385 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9387 MonoProperty* property;
9391 mono_class_setup_properties (klass);
9392 MonoClassExt *ext = mono_class_get_ext (klass);
9393 /* start from the first */
9394 if (ext->property.count) {
9395 *iter = &ext->properties [0];
9396 return (MonoProperty *)*iter;
9402 property = (MonoProperty *)*iter;
9404 MonoClassExt *ext = mono_class_get_ext (klass);
9405 if (property < &ext->properties [ext->property.count]) {
9407 return (MonoProperty *)*iter;
9413 * mono_class_get_events:
9414 * @klass: the MonoClass to act on
9416 * This routine is an iterator routine for retrieving the properties in a class.
9418 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9419 * iterate over all of the elements. When no more values are
9420 * available, the return value is NULL.
9422 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9425 mono_class_get_events (MonoClass* klass, gpointer *iter)
9431 mono_class_setup_events (klass);
9432 MonoClassExt *ext = mono_class_get_ext (klass);
9433 /* start from the first */
9434 if (ext->event.count) {
9435 *iter = &ext->events [0];
9436 return (MonoEvent *)*iter;
9442 event = (MonoEvent *)*iter;
9444 MonoClassExt *ext = mono_class_get_ext (klass);
9445 if (event < &ext->events [ext->event.count]) {
9447 return (MonoEvent *)*iter;
9453 * mono_class_get_interfaces
9454 * @klass: the MonoClass to act on
9456 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9458 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9459 * iterate over all of the elements. When no more values are
9460 * available, the return value is NULL.
9462 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9465 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9473 mono_class_init (klass);
9474 if (!klass->interfaces_inited) {
9475 mono_class_setup_interfaces (klass, &error);
9476 if (!mono_error_ok (&error)) {
9477 mono_error_cleanup (&error);
9481 /* start from the first */
9482 if (klass->interface_count) {
9483 *iter = &klass->interfaces [0];
9484 return klass->interfaces [0];
9490 iface = (MonoClass **)*iter;
9492 if (iface < &klass->interfaces [klass->interface_count]) {
9500 setup_nested_types (MonoClass *klass)
9503 GList *classes, *nested_classes, *l;
9506 if (klass->nested_classes_inited)
9509 if (!klass->type_token)
9510 klass->nested_classes_inited = TRUE;
9512 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9516 guint32 cols [MONO_NESTED_CLASS_SIZE];
9517 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9518 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9519 if (!mono_error_ok (&error)) {
9520 /*FIXME don't swallow the error message*/
9521 mono_error_cleanup (&error);
9523 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9527 classes = g_list_prepend (classes, nclass);
9529 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9532 mono_class_alloc_ext (klass);
9534 nested_classes = NULL;
9535 for (l = classes; l; l = l->next)
9536 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9537 g_list_free (classes);
9539 mono_image_lock (klass->image);
9541 mono_memory_barrier ();
9542 if (!klass->nested_classes_inited) {
9543 mono_class_get_ext (klass)->nested_classes = nested_classes;
9544 mono_memory_barrier ();
9545 klass->nested_classes_inited = TRUE;
9548 mono_image_unlock (klass->image);
9552 * mono_class_get_nested_types
9553 * @klass: the MonoClass to act on
9555 * This routine is an iterator routine for retrieving the nested types of a class.
9556 * This works only if @klass is non-generic, or a generic type definition.
9558 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9559 * iterate over all of the elements. When no more values are
9560 * available, the return value is NULL.
9562 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9565 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9571 if (!klass->nested_classes_inited)
9572 setup_nested_types (klass);
9575 MonoClassExt *ext = mono_class_get_ext (klass);
9576 /* start from the first */
9577 if (ext && ext->nested_classes) {
9578 *iter = ext->nested_classes;
9579 return (MonoClass *)ext->nested_classes->data;
9581 /* no nested types */
9585 item = (GList *)*iter;
9589 return (MonoClass *)item->data;
9596 * mono_class_is_delegate
9597 * @klass: the MonoClass to act on
9599 * Returns: TRUE if the MonoClass represents a System.Delegate.
9602 mono_class_is_delegate (MonoClass *klass)
9604 return klass->delegate;
9608 * mono_class_implements_interface
9609 * @klass: The MonoClass to act on
9610 * @interface: The interface to check if @klass implements.
9612 * Returns: TRUE if @klass implements @interface.
9615 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9617 return mono_class_is_assignable_from (iface, klass);
9621 * mono_field_get_name:
9622 * @field: the MonoClassField to act on
9624 * Returns: The name of the field.
9627 mono_field_get_name (MonoClassField *field)
9633 * mono_field_get_type:
9634 * @field: the MonoClassField to act on
9636 * Returns: MonoType of the field.
9639 mono_field_get_type (MonoClassField *field)
9642 MonoType *type = mono_field_get_type_checked (field, &error);
9643 if (!mono_error_ok (&error)) {
9644 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9645 mono_error_cleanup (&error);
9652 * mono_field_get_type_checked:
9653 * @field: the MonoClassField to act on
9654 * @error: used to return any erro found while retrieving @field type
9656 * Returns: MonoType of the field.
9659 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9661 mono_error_init (error);
9663 mono_field_resolve_type (field, error);
9668 * mono_field_get_parent:
9669 * @field: the MonoClassField to act on
9671 * Returns: MonoClass where the field was defined.
9674 mono_field_get_parent (MonoClassField *field)
9676 return field->parent;
9680 * mono_field_get_flags;
9681 * @field: the MonoClassField to act on
9683 * The metadata flags for a field are encoded using the
9684 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9686 * Returns: The flags for the field.
9689 mono_field_get_flags (MonoClassField *field)
9692 return mono_field_resolve_flags (field);
9693 return field->type->attrs;
9697 * mono_field_get_offset:
9698 * @field: the MonoClassField to act on
9700 * Returns: The field offset.
9703 mono_field_get_offset (MonoClassField *field)
9705 return field->offset;
9709 mono_field_get_rva (MonoClassField *field)
9713 MonoClass *klass = field->parent;
9714 MonoFieldDefaultValue *field_def_values;
9716 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9718 MonoClassExt *ext = mono_class_get_ext (klass);
9719 if (!ext || !ext->field_def_values) {
9720 mono_class_alloc_ext (klass);
9721 ext = mono_class_get_ext (klass);
9723 field_def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
9725 mono_image_lock (klass->image);
9726 if (!ext->field_def_values)
9727 ext->field_def_values = field_def_values;
9728 mono_image_unlock (klass->image);
9731 field_index = mono_field_get_index (field);
9733 if (!ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9734 int first_field_idx = mono_class_get_first_field_idx (klass);
9735 mono_metadata_field_info (field->parent->image, first_field_idx + field_index, NULL, &rva, NULL);
9737 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9738 ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9741 return ext->field_def_values [field_index].data;
9745 * mono_field_get_data:
9746 * @field: the MonoClassField to act on
9748 * Returns: A pointer to the metadata constant value or to the field
9749 * data if it has an RVA flag.
9752 mono_field_get_data (MonoClassField *field)
9754 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9755 MonoTypeEnum def_type;
9757 return mono_class_get_field_default_value (field, &def_type);
9758 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9759 return mono_field_get_rva (field);
9766 * mono_property_get_name:
9767 * @prop: the MonoProperty to act on
9769 * Returns: The name of the property
9772 mono_property_get_name (MonoProperty *prop)
9778 * mono_property_get_set_method
9779 * @prop: the MonoProperty to act on.
9781 * Returns: The setter method of the property (A MonoMethod)
9784 mono_property_get_set_method (MonoProperty *prop)
9790 * mono_property_get_get_method
9791 * @prop: the MonoProperty to act on.
9793 * Returns: The setter method of the property (A MonoMethod)
9796 mono_property_get_get_method (MonoProperty *prop)
9802 * mono_property_get_parent:
9803 * @prop: the MonoProperty to act on.
9805 * Returns: The MonoClass where the property was defined.
9808 mono_property_get_parent (MonoProperty *prop)
9810 return prop->parent;
9814 * mono_property_get_flags:
9815 * @prop: the MonoProperty to act on.
9817 * The metadata flags for a property are encoded using the
9818 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9820 * Returns: The flags for the property.
9823 mono_property_get_flags (MonoProperty *prop)
9829 * mono_event_get_name:
9830 * @event: the MonoEvent to act on
9832 * Returns: The name of the event.
9835 mono_event_get_name (MonoEvent *event)
9841 * mono_event_get_add_method:
9842 * @event: The MonoEvent to act on.
9844 * Returns: The @add' method for the event (a MonoMethod).
9847 mono_event_get_add_method (MonoEvent *event)
9853 * mono_event_get_remove_method:
9854 * @event: The MonoEvent to act on.
9856 * Returns: The @remove method for the event (a MonoMethod).
9859 mono_event_get_remove_method (MonoEvent *event)
9861 return event->remove;
9865 * mono_event_get_raise_method:
9866 * @event: The MonoEvent to act on.
9868 * Returns: The @raise method for the event (a MonoMethod).
9871 mono_event_get_raise_method (MonoEvent *event)
9873 return event->raise;
9877 * mono_event_get_parent:
9878 * @event: the MonoEvent to act on.
9880 * Returns: The MonoClass where the event is defined.
9883 mono_event_get_parent (MonoEvent *event)
9885 return event->parent;
9889 * mono_event_get_flags
9890 * @event: the MonoEvent to act on.
9892 * The metadata flags for an event are encoded using the
9893 * EVENT_* constants. See the tabledefs.h file for details.
9895 * Returns: The flags for the event.
9898 mono_event_get_flags (MonoEvent *event)
9900 return event->attrs;
9904 * mono_class_get_method_from_name:
9905 * @klass: where to look for the method
9906 * @name: name of the method
9907 * @param_count: number of parameters. -1 for any number.
9909 * Obtains a MonoMethod with a given name and number of parameters.
9910 * It only works if there are no multiple signatures for any given method name.
9913 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9915 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9919 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9921 MonoMethod *res = NULL;
9924 /* Search directly in the metadata to avoid calling setup_methods () */
9925 int first_idx = mono_class_get_first_method_idx (klass);
9926 int mcount = mono_class_get_method_count (klass);
9927 for (i = 0; i < mcount; ++i) {
9929 guint32 cols [MONO_METHOD_SIZE];
9931 MonoMethodSignature *sig;
9933 /* first_idx points into the methodptr table */
9934 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, first_idx + i, cols, MONO_METHOD_SIZE);
9936 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9937 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9939 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9942 if (param_count == -1) {
9946 sig = mono_method_signature_checked (method, &error);
9948 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9951 if (sig->param_count == param_count) {
9962 * mono_class_get_method_from_name_flags:
9963 * @klass: where to look for the method
9964 * @name_space: name of the method
9965 * @param_count: number of parameters. -1 for any number.
9966 * @flags: flags which must be set in the method
9968 * Obtains a MonoMethod with a given name and number of parameters.
9969 * It only works if there are no multiple signatures for any given method name.
9972 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9974 MonoMethod *res = NULL;
9977 mono_class_init (klass);
9979 if (mono_class_is_ginst (klass) && !klass->methods) {
9980 res = mono_class_get_method_from_name_flags (mono_class_get_generic_class (klass)->container_class, name, param_count, flags);
9983 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9984 if (!mono_error_ok (&error))
9985 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9990 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9991 mono_class_setup_methods (klass);
9993 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9994 See mono/tests/array_load_exception.il
9995 FIXME we should better report this error to the caller
9997 if (!klass->methods)
9999 int mcount = mono_class_get_method_count (klass);
10000 for (i = 0; i < mcount; ++i) {
10001 MonoMethod *method = klass->methods [i];
10003 if (method->name[0] == name [0] &&
10004 !strcmp (name, method->name) &&
10005 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
10006 ((method->flags & flags) == flags)) {
10013 res = find_method_in_metadata (klass, name, param_count, flags);
10020 * mono_class_set_failure:
10021 * @klass: class in which the failure was detected
10022 * @ex_type: the kind of exception/error to be thrown (later)
10023 * @ex_data: exception data (specific to each type of exception/error)
10025 * Keep a detected failure informations in the class for later processing.
10026 * Note that only the first failure is kept.
10028 * LOCKING: Acquires the loader lock.
10031 mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error)
10033 g_assert (boxed_error != NULL);
10035 if (mono_class_has_failure (klass))
10038 mono_loader_lock ();
10039 klass->has_failure = 1;
10040 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, boxed_error);
10041 mono_loader_unlock ();
10047 mono_class_has_failure (const MonoClass *klass)
10049 g_assert (klass != NULL);
10050 return klass->has_failure != 0;
10055 * mono_class_set_type_load_failure:
10056 * @klass: class in which the failure was detected
10057 * @fmt: Printf-style error message string.
10059 * Collect detected failure informaion in the class for later processing.
10060 * The error is stored as a MonoErrorBoxed as with mono_error_set_type_load_class ()
10061 * Note that only the first failure is kept.
10063 * Returns FALSE if a failure was already set on the class, or TRUE otherwise.
10065 * LOCKING: Acquires the loader lock.
10068 mono_class_set_type_load_failure (MonoClass *klass, const char * fmt, ...)
10070 MonoError prepare_error;
10073 if (mono_class_has_failure (klass))
10076 mono_error_init (&prepare_error);
10078 va_start (args, fmt);
10079 mono_error_vset_type_load_class (&prepare_error, klass, fmt, args);
10082 MonoErrorBoxed *box = mono_error_box (&prepare_error, klass->image);
10083 mono_error_cleanup (&prepare_error);
10084 return mono_class_set_failure (klass, box);
10088 * mono_class_get_exception_data:
10090 * Return the exception_data property of KLASS.
10092 * LOCKING: Acquires the loader lock.
10095 mono_class_get_exception_data (const MonoClass *klass)
10097 return mono_image_property_lookup (klass->image, (MonoClass*)klass, MONO_CLASS_PROP_EXCEPTION_DATA);
10101 * mono_classes_init:
10103 * Initialize the resources used by this module.
10106 mono_classes_init (void)
10108 mono_os_mutex_init (&classes_mutex);
10110 mono_native_tls_alloc (&setup_fields_tls_id, NULL);
10111 mono_native_tls_alloc (&init_pending_tls_id, NULL);
10113 mono_counters_register ("MonoClassDef count",
10114 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_def_count);
10115 mono_counters_register ("MonoClassGtd count",
10116 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gtd_count);
10117 mono_counters_register ("MonoClassGenericInst count",
10118 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ginst_count);
10119 mono_counters_register ("MonoClassGenericParam count",
10120 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gparam_count);
10121 mono_counters_register ("MonoClassArray count",
10122 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_array_count);
10123 mono_counters_register ("MonoClassPointer count",
10124 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_pointer_count);
10125 mono_counters_register ("Inflated methods size",
10126 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
10127 mono_counters_register ("Inflated classes size",
10128 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
10129 mono_counters_register ("MonoClass size",
10130 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
10131 mono_counters_register ("MonoClassExt size",
10132 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
10134 mono_counters_register ("MonoClassExt count",
10135 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_count);
10139 * mono_classes_cleanup:
10141 * Free the resources used by this module.
10144 mono_classes_cleanup (void)
10146 mono_native_tls_free (setup_fields_tls_id);
10147 mono_native_tls_free (init_pending_tls_id);
10149 if (global_interface_bitset)
10150 mono_bitset_free (global_interface_bitset);
10151 global_interface_bitset = NULL;
10152 mono_os_mutex_destroy (&classes_mutex);
10156 * mono_class_get_exception_for_failure:
10157 * @klass: class in which the failure was detected
10159 * Return a constructed MonoException than the caller can then throw
10160 * using mono_raise_exception - or NULL if no failure is present (or
10161 * doesn't result in an exception).
10164 mono_class_get_exception_for_failure (MonoClass *klass)
10166 if (!mono_class_has_failure (klass))
10168 MonoError unboxed_error;
10169 mono_error_init (&unboxed_error);
10170 mono_error_set_for_class_failure (&unboxed_error, klass);
10171 return mono_error_convert_to_exception (&unboxed_error);
10175 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
10177 outer_klass = mono_class_get_generic_type_definition (outer_klass);
10178 inner_klass = mono_class_get_generic_type_definition (inner_klass);
10180 if (outer_klass == inner_klass)
10182 inner_klass = inner_klass->nested_in;
10183 } while (inner_klass);
10188 mono_class_get_generic_type_definition (MonoClass *klass)
10190 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
10191 return gklass ? gklass->container_class : klass;
10195 * Check if @klass is a subtype of @parent ignoring generic instantiations.
10197 * Generic instantiations are ignored for all super types of @klass.
10199 * Visibility checks ignoring generic instantiations.
10202 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
10205 klass = mono_class_get_generic_type_definition (klass);
10206 parent = mono_class_get_generic_type_definition (parent);
10207 mono_class_setup_supertypes (klass);
10209 for (i = 0; i < klass->idepth; ++i) {
10210 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
10216 * Subtype can only access parent members with family protection if the site object
10217 * is subclass of Subtype. For example:
10218 * class A { protected int x; }
10220 * void valid_access () {
10224 * void invalid_access () {
10231 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
10233 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
10236 if (context_klass == NULL)
10238 /*if access_klass is not member_klass context_klass must be type compat*/
10239 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10245 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10248 if (accessing == accessed)
10250 if (!accessed || !accessing)
10253 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10254 * anywhere so untrusted friends are not safe to access platform's code internals */
10255 if (mono_security_core_clr_enabled ()) {
10256 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10260 mono_assembly_load_friends (accessed);
10261 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10262 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10263 /* Be conservative with checks */
10264 if (!friend_->name)
10266 if (strcmp (accessing->aname.name, friend_->name))
10268 if (friend_->public_key_token [0]) {
10269 if (!accessing->aname.public_key_token [0])
10271 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10280 * If klass is a generic type or if it is derived from a generic type, return the
10281 * MonoClass of the generic definition
10282 * Returns NULL if not found
10285 get_generic_definition_class (MonoClass *klass)
10288 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
10289 if (gklass && gklass->container_class)
10290 return gklass->container_class;
10291 klass = klass->parent;
10297 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10300 for (i = 0; i < ginst->type_argc; ++i) {
10301 MonoType *type = ginst->type_argv[i];
10302 switch (type->type) {
10303 case MONO_TYPE_SZARRAY:
10304 if (!can_access_type (access_klass, type->data.klass))
10307 case MONO_TYPE_ARRAY:
10308 if (!can_access_type (access_klass, type->data.array->eklass))
10311 case MONO_TYPE_PTR:
10312 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10315 case MONO_TYPE_CLASS:
10316 case MONO_TYPE_VALUETYPE:
10317 case MONO_TYPE_GENERICINST:
10318 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10328 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10332 if (access_klass == member_klass)
10335 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10338 if (access_klass->element_class && !access_klass->enumtype)
10339 access_klass = access_klass->element_class;
10341 if (member_klass->element_class && !member_klass->enumtype)
10342 member_klass = member_klass->element_class;
10344 access_level = mono_class_get_flags (member_klass) & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10346 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10349 if (mono_class_is_ginst (member_klass) && !can_access_instantiation (access_klass, mono_class_get_generic_class (member_klass)->context.class_inst))
10352 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10355 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10358 /*Non nested type with nested visibility. We just fail it.*/
10359 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10362 switch (access_level) {
10363 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10364 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10366 case TYPE_ATTRIBUTE_PUBLIC:
10369 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10372 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10373 return is_nesting_type (member_klass, access_klass);
10375 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10376 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10378 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10379 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10381 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10382 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10383 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10385 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10386 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10387 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10392 /* FIXME: check visibility of type, too */
10394 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10396 MonoClass *member_generic_def;
10397 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10400 MonoGenericClass *access_gklass = mono_class_try_get_generic_class (access_klass);
10401 if (((access_gklass && access_gklass->container_class) ||
10402 mono_class_is_gtd (access_klass)) &&
10403 (member_generic_def = get_generic_definition_class (member_klass))) {
10404 MonoClass *access_container;
10406 if (mono_class_is_gtd (access_klass))
10407 access_container = access_klass;
10409 access_container = access_gklass->container_class;
10411 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10415 /* Partition I 8.5.3.2 */
10416 /* the access level values are the same for fields and methods */
10417 switch (access_level) {
10418 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10419 /* same compilation unit */
10420 return access_klass->image == member_klass->image;
10421 case FIELD_ATTRIBUTE_PRIVATE:
10422 return access_klass == member_klass;
10423 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10424 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10425 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10428 case FIELD_ATTRIBUTE_ASSEMBLY:
10429 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10430 case FIELD_ATTRIBUTE_FAMILY:
10431 if (is_valid_family_access (access_klass, member_klass, context_klass))
10434 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10435 if (is_valid_family_access (access_klass, member_klass, context_klass))
10437 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10438 case FIELD_ATTRIBUTE_PUBLIC:
10445 * mono_method_can_access_field:
10446 * @method: Method that will attempt to access the field
10447 * @field: the field to access
10449 * Used to determine if a method is allowed to access the specified field.
10451 * Returns: TRUE if the given @method is allowed to access the @field while following
10452 * the accessibility rules of the CLI.
10455 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10457 /* FIXME: check all overlapping fields */
10458 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10460 MonoClass *nested = method->klass->nested_in;
10462 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10465 nested = nested->nested_in;
10472 * mono_method_can_access_method:
10473 * @method: Method that will attempt to access the other method
10474 * @called: the method that we want to probe for accessibility.
10476 * Used to determine if the @method is allowed to access the specified @called method.
10478 * Returns: TRUE if the given @method is allowed to invoke the @called while following
10479 * the accessibility rules of the CLI.
10482 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10484 method = mono_method_get_method_definition (method);
10485 called = mono_method_get_method_definition (called);
10486 return mono_method_can_access_method_full (method, called, NULL);
10490 * mono_method_can_access_method_full:
10491 * @method: The caller method
10492 * @called: The called method
10493 * @context_klass: The static type on stack of the owner @called object used
10495 * This function must be used with instance calls, as they have more strict family accessibility.
10496 * It can be used with static methods, but context_klass should be NULL.
10498 * Returns: TRUE if caller have proper visibility and acessibility to @called
10501 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10503 /* Wrappers are except from access checks */
10504 if (method->wrapper_type != MONO_WRAPPER_NONE || called->wrapper_type != MONO_WRAPPER_NONE)
10507 MonoClass *access_class = method->klass;
10508 MonoClass *member_class = called->klass;
10509 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10511 MonoClass *nested = access_class->nested_in;
10513 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10516 nested = nested->nested_in;
10523 can = can_access_type (access_class, member_class);
10525 MonoClass *nested = access_class->nested_in;
10527 can = can_access_type (nested, member_class);
10530 nested = nested->nested_in;
10537 if (called->is_inflated) {
10538 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10539 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10548 * mono_method_can_access_field_full:
10549 * @method: The caller method
10550 * @field: The accessed field
10551 * @context_klass: The static type on stack of the owner @field object used
10553 * This function must be used with instance fields, as they have more strict family accessibility.
10554 * It can be used with static fields, but context_klass should be NULL.
10556 * Returns: TRUE if caller have proper visibility and acessibility to @field
10559 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10561 MonoClass *access_class = method->klass;
10562 MonoClass *member_class = field->parent;
10563 /* FIXME: check all overlapping fields */
10564 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10566 MonoClass *nested = access_class->nested_in;
10568 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10571 nested = nested->nested_in;
10578 can = can_access_type (access_class, member_class);
10580 MonoClass *nested = access_class->nested_in;
10582 can = can_access_type (nested, member_class);
10585 nested = nested->nested_in;
10595 * mono_class_can_access_class:
10596 * @source_class: The source class
10597 * @target_class: The accessed class
10599 * This function returns is @target_class is visible to @source_class
10601 * Returns: TRUE if source have proper visibility and acessibility to target
10604 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10606 return can_access_type (source_class, target_class);
10610 * mono_type_is_valid_enum_basetype:
10611 * @type: The MonoType to check
10613 * Returns: TRUE if the type can be used as the basetype of an enum
10615 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10616 switch (type->type) {
10619 case MONO_TYPE_BOOLEAN:
10622 case MONO_TYPE_CHAR:
10636 * mono_class_is_valid_enum:
10637 * @klass: An enum class to be validated
10639 * This method verify the required properties an enum should have.
10641 * Returns: TRUE if the informed enum class is valid
10643 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10644 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10645 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10648 mono_class_is_valid_enum (MonoClass *klass)
10650 MonoClassField * field;
10651 gpointer iter = NULL;
10652 gboolean found_base_field = FALSE;
10654 g_assert (klass->enumtype);
10655 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10656 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10660 if (!mono_class_is_auto_layout (klass))
10663 while ((field = mono_class_get_fields (klass, &iter))) {
10664 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10665 if (found_base_field)
10667 found_base_field = TRUE;
10668 if (!mono_type_is_valid_enum_basetype (field->type))
10673 if (!found_base_field)
10676 if (mono_class_get_method_count (klass) > 0)
10683 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10685 return gklass->context.class_inst == mono_class_get_generic_container (gklass->container_class)->context.class_inst;
10689 * mono_class_setup_interface_id:
10691 * Initializes MonoClass::interface_id if required.
10693 * LOCKING: Acquires the loader lock.
10696 mono_class_setup_interface_id (MonoClass *klass)
10698 mono_loader_lock ();
10699 if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10700 klass->interface_id = mono_get_unique_iid (klass);
10701 mono_loader_unlock ();
10705 * mono_class_alloc_ext:
10707 * Allocate klass->ext if not already done.
10710 mono_class_alloc_ext (MonoClass *klass)
10714 if (mono_class_get_ext (klass))
10717 ext = (MonoClassExt *)mono_class_alloc0 (klass, sizeof (MonoClassExt));
10718 mono_image_lock (klass->image);
10719 mono_memory_barrier ();
10720 if (!mono_class_get_ext (klass))
10721 mono_class_set_ext (klass, ext);
10722 class_ext_size += sizeof (MonoClassExt);
10724 mono_image_unlock (klass->image);
10728 * mono_class_setup_interfaces:
10730 * Initialize klass->interfaces/interfaces_count.
10731 * LOCKING: Acquires the loader lock.
10732 * This function can fail the type.
10735 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10737 int i, interface_count;
10738 MonoClass **interfaces;
10740 mono_error_init (error);
10742 if (klass->interfaces_inited)
10745 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10746 MonoType *args [1];
10748 /* generic IList, ICollection, IEnumerable */
10749 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10750 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10752 args [0] = &klass->element_class->byval_arg;
10753 interfaces [0] = mono_class_bind_generic_parameters (
10754 mono_defaults.generic_ilist_class, 1, args, FALSE);
10755 if (interface_count > 1)
10756 interfaces [1] = mono_class_bind_generic_parameters (
10757 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10758 } else if (mono_class_is_ginst (klass)) {
10759 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
10761 mono_class_setup_interfaces (gklass, error);
10762 if (!mono_error_ok (error)) {
10763 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10767 interface_count = gklass->interface_count;
10768 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10769 for (i = 0; i < interface_count; i++) {
10770 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (mono_class_get_generic_class (klass)), error);
10771 if (!mono_error_ok (error)) {
10772 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10777 interface_count = 0;
10781 mono_image_lock (klass->image);
10783 if (!klass->interfaces_inited) {
10784 klass->interface_count = interface_count;
10785 klass->interfaces = interfaces;
10787 mono_memory_barrier ();
10789 klass->interfaces_inited = TRUE;
10792 mono_image_unlock (klass->image);
10796 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10798 MonoClass *klass = field->parent;
10799 MonoImage *image = klass->image;
10800 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10802 int field_idx = field - klass->fields;
10804 mono_error_init (error);
10807 MonoClassField *gfield = >d->fields [field_idx];
10808 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10809 if (!mono_error_ok (error)) {
10810 char *full_name = mono_type_get_full_name (gtd);
10811 mono_class_set_type_load_failure (klass, "Could not load generic type of field '%s:%s' (%d) due to: %s", full_name, gfield->name, field_idx, mono_error_get_message (error));
10812 g_free (full_name);
10815 ftype = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10816 if (!mono_error_ok (error)) {
10817 char *full_name = mono_type_get_full_name (klass);
10818 mono_class_set_type_load_failure (klass, "Could not load instantiated type of field '%s:%s' (%d) due to: %s", full_name, field->name, field_idx, mono_error_get_message (error));
10819 g_free (full_name);
10823 guint32 cols [MONO_FIELD_SIZE];
10824 MonoGenericContainer *container = NULL;
10825 int idx = mono_class_get_first_field_idx (klass) + field_idx;
10827 /*FIXME, in theory we do not lazy load SRE fields*/
10828 g_assert (!image_is_dynamic (image));
10830 if (mono_class_is_gtd (klass)) {
10831 container = mono_class_get_generic_container (klass);
10833 container = mono_class_get_generic_container (gtd);
10834 g_assert (container);
10837 /* first_field_idx and idx points into the fieldptr table */
10838 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10840 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10841 char *full_name = mono_type_get_full_name (klass);
10842 mono_error_set_type_load_class (error, klass, "Could not verify field '%s:%s' signature", full_name, field->name);;
10843 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
10844 g_free (full_name);
10848 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10850 mono_metadata_decode_value (sig, &sig);
10851 /* FIELD signature == 0x06 */
10852 g_assert (*sig == 0x06);
10854 ftype = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10856 char *full_name = mono_type_get_full_name (klass);
10857 mono_class_set_type_load_failure (klass, "Could not load type of field '%s:%s' (%d) due to: %s", full_name, field->name, field_idx, mono_error_get_message (error));
10858 g_free (full_name);
10861 mono_memory_barrier ();
10862 field->type = ftype;
10866 mono_field_resolve_flags (MonoClassField *field)
10868 MonoClass *klass = field->parent;
10869 MonoImage *image = klass->image;
10870 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10871 int field_idx = field - klass->fields;
10875 MonoClassField *gfield = >d->fields [field_idx];
10876 return mono_field_get_flags (gfield);
10878 int idx = mono_class_get_first_field_idx (klass) + field_idx;
10880 /*FIXME, in theory we do not lazy load SRE fields*/
10881 g_assert (!image_is_dynamic (image));
10883 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10888 * mono_class_get_fields_lazy:
10889 * @klass: the MonoClass to act on
10891 * This routine is an iterator routine for retrieving the fields in a class.
10892 * Only minimal information about fields are loaded. Accessors must be used
10893 * for all MonoClassField returned.
10895 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10896 * iterate over all of the elements. When no more values are
10897 * available, the return value is NULL.
10899 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10902 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10904 MonoClassField* field;
10908 mono_class_setup_basic_field_info (klass);
10909 if (!klass->fields)
10911 /* start from the first */
10912 if (mono_class_get_field_count (klass)) {
10913 *iter = &klass->fields [0];
10914 return (MonoClassField *)*iter;
10920 field = (MonoClassField *)*iter;
10922 if (field < &klass->fields [mono_class_get_field_count (klass)]) {
10924 return (MonoClassField *)*iter;
10930 mono_class_full_name (MonoClass *klass)
10932 return mono_type_full_name (&klass->byval_arg);
10935 /* Declare all shared lazy type lookup functions */
10936 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, System.Runtime.InteropServices, SafeHandle)