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 mono_loader_lock ();
6085 if (gclass->cached_class) {
6086 mono_loader_unlock ();
6087 return gclass->cached_class;
6090 klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClassGenericInst));
6092 gklass = gclass->container_class;
6094 if (record_gclass_instantiation > 0)
6095 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
6097 if (gklass->nested_in) {
6098 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
6099 klass->nested_in = gklass->nested_in;
6102 klass->name = gklass->name;
6103 klass->name_space = gklass->name_space;
6105 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6107 klass->image = gklass->image;
6108 klass->type_token = gklass->type_token;
6110 klass->class_kind = MONO_CLASS_GINST;
6112 ((MonoClassGenericInst*)klass)->generic_class = gclass;
6114 klass->byval_arg.type = MONO_TYPE_GENERICINST;
6115 klass->this_arg.type = klass->byval_arg.type;
6116 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
6117 klass->this_arg.byref = TRUE;
6118 klass->enumtype = gklass->enumtype;
6119 klass->valuetype = gklass->valuetype;
6120 klass->simd_type = gklass->simd_type;
6122 klass->cast_class = klass->element_class = klass;
6124 if (mono_class_is_nullable (klass))
6125 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
6128 * We're not interested in the nested classes of a generic instance.
6129 * We use the generic type definition to look for nested classes.
6132 mono_generic_class_setup_parent (klass, gklass);
6134 if (gclass->is_dynamic) {
6136 * 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.
6137 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
6138 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
6140 if (!gklass->wastypebuilder)
6143 mono_class_setup_supertypes (klass);
6145 if (klass->enumtype) {
6147 * For enums, gklass->fields might not been set, but instance_size etc. is
6148 * already set in mono_reflection_create_internal_class (). For non-enums,
6149 * these will be computed normally in mono_class_layout_fields ().
6151 klass->instance_size = gklass->instance_size;
6152 klass->sizes.class_size = gklass->sizes.class_size;
6153 mono_memory_barrier ();
6154 klass->size_inited = 1;
6158 mono_memory_barrier ();
6159 gclass->cached_class = klass;
6161 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6163 ++class_ginst_count;
6164 inflated_classes_size += sizeof (MonoClassGenericInst);
6166 mono_loader_unlock ();
6172 get_image_for_container (MonoGenericContainer *container)
6175 if (container->is_anonymous) {
6176 result = container->owner.image;
6179 if (container->is_method) {
6180 MonoMethod *method = container->owner.method;
6181 g_assert_checked (method);
6182 klass = method->klass;
6184 klass = container->owner.klass;
6186 g_assert_checked (klass);
6187 result = klass->image;
6194 get_image_for_generic_param (MonoGenericParam *param)
6196 MonoGenericContainer *container = mono_generic_param_owner (param);
6197 g_assert_checked (container);
6198 return get_image_for_container (container);
6201 // Make a string in the designated image consisting of a single integer.
6202 #define INT_STRING_SIZE 16
6204 make_generic_name_string (MonoImage *image, int num)
6206 char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
6207 g_snprintf (name, INT_STRING_SIZE, "%d", num);
6211 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
6212 // pinfo is derived from param by the caller for us.
6214 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
6216 MonoClass *klass, **ptr;
6218 MonoGenericContainer *container = mono_generic_param_owner (param);
6219 g_assert_checked (container);
6221 MonoImage *image = get_image_for_container (container);
6222 gboolean is_mvar = container->is_method;
6223 gboolean is_anonymous = container->is_anonymous;
6225 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassGenericParam));
6226 klass->class_kind = MONO_CLASS_GPARAM;
6227 classes_size += sizeof (MonoClassGenericParam);
6228 ++class_gparam_count;
6231 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
6233 int n = mono_generic_param_num (param);
6234 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
6238 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , "" );
6239 } else if (is_mvar) {
6240 MonoMethod *omethod = container->owner.method;
6241 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
6243 MonoClass *oklass = container->owner.klass;
6244 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
6247 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6249 // Count non-NULL items in pinfo->constraints
6252 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6256 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6257 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
6259 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
6260 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
6262 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
6265 if (count - pos > 0) {
6266 klass->interface_count = count - pos;
6267 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
6268 klass->interfaces_inited = TRUE;
6269 for (i = pos; i < count; i++)
6270 CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
6273 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
6275 klass->inited = TRUE;
6276 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class , klass );
6277 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
6279 klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6280 klass->this_arg.type = klass->byval_arg.type;
6281 CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param , param );
6282 CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
6283 klass->this_arg.byref = TRUE;
6285 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6286 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6288 /*Init these fields to sane values*/
6289 klass->min_align = 1;
6291 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6292 * constrained to, the JIT depends on this.
6294 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6295 mono_memory_barrier ();
6296 klass->size_inited = 1;
6298 mono_class_setup_supertypes (klass);
6300 if (count - pos > 0) {
6301 mono_class_setup_vtable (klass->parent);
6302 if (mono_class_has_failure (klass->parent))
6303 mono_class_set_type_load_failure (klass, "Failed to setup parent interfaces");
6305 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6311 #define FAST_CACHE_SIZE 16
6314 * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6315 * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6316 * we cache the MonoClasses.
6317 * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6318 * LOCKING: Takes the image lock depending on @take_lock.
6321 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6323 int n = mono_generic_param_num (param);
6324 MonoImage *image = get_image_for_generic_param (param);
6325 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6326 MonoClass *klass = NULL;
6331 // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6332 // For high numbers or constraints we have to use pointer hashes.
6333 if (param->gshared_constraint) {
6334 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6337 mono_image_lock (image);
6338 klass = (MonoClass *)g_hash_table_lookup (ht, param);
6340 mono_image_unlock (image);
6345 if (n < FAST_CACHE_SIZE) {
6347 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6349 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6351 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6354 mono_image_lock (image);
6355 klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6357 mono_image_unlock (image);
6364 * LOCKING: Image lock (param->image) must be held
6367 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6369 int n = mono_generic_param_num (param);
6370 MonoImage *image = get_image_for_generic_param (param);
6371 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6375 if (param->gshared_constraint) {
6376 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6378 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6379 mono_memory_barrier ();
6381 image->mvar_cache_constrained = ht;
6383 image->var_cache_constrained = ht;
6385 g_hash_table_insert (ht, param, klass);
6386 } else if (n < FAST_CACHE_SIZE) {
6388 /* Requires locking to avoid droping an already published class */
6389 if (!image->mvar_cache_fast)
6390 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6391 image->mvar_cache_fast [n] = klass;
6393 if (!image->var_cache_fast)
6394 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6395 image->var_cache_fast [n] = klass;
6398 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6400 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6402 ht = g_hash_table_new (NULL, NULL);
6403 mono_memory_barrier ();
6405 image->mvar_cache_slow = ht;
6407 image->var_cache_slow = ht;
6410 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6415 * LOCKING: Acquires the image lock (@image).
6418 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6420 MonoImage *image = get_image_for_generic_param (param);
6421 MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6422 MonoClass *klass, *klass2;
6424 // If a klass already exists for this object and is cached, return it.
6425 if (pinfo) // Non-anonymous
6426 klass = pinfo->pklass;
6428 klass = get_anon_gparam_class (param, TRUE);
6433 // Create a new klass
6434 klass = make_generic_param_class (param, pinfo);
6436 // Now we need to cache the klass we created.
6437 // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6438 // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6439 // and allow our newly-created klass object to just leak.
6440 mono_memory_barrier ();
6442 mono_image_lock (image);
6444 // Here "klass2" refers to the klass potentially created by the other thread.
6445 if (pinfo) // Repeat check from above
6446 klass2 = pinfo->pklass;
6448 klass2 = get_anon_gparam_class (param, FALSE);
6455 pinfo->pklass = klass;
6457 set_anon_gparam_class (param, klass);
6459 mono_image_unlock (image);
6461 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6463 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED); // Alert profiler about botched class create
6465 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6471 * mono_class_from_generic_parameter:
6472 * @param: Parameter to find/construct a class for.
6473 * @arg2: Is ignored.
6474 * @arg3: Is ignored.
6477 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6479 return mono_class_from_generic_parameter_internal (param);
6484 mono_ptr_class_get (MonoType *type)
6487 MonoClass *el_class;
6491 el_class = mono_class_from_mono_type (type);
6492 image = el_class->image;
6494 mono_image_lock (image);
6495 if (image->ptr_cache) {
6496 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6497 mono_image_unlock (image);
6501 mono_image_unlock (image);
6503 result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassPointer));
6505 classes_size += sizeof (MonoClassPointer);
6506 ++class_pointer_count;
6508 result->parent = NULL; /* no parent for PTR types */
6509 result->name_space = el_class->name_space;
6510 name = g_strdup_printf ("%s*", el_class->name);
6511 result->name = mono_image_strdup (image, name);
6512 result->class_kind = MONO_CLASS_POINTER;
6515 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6517 result->image = el_class->image;
6518 result->inited = TRUE;
6519 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6520 result->cast_class = result->element_class = el_class;
6521 result->blittable = TRUE;
6523 result->byval_arg.type = MONO_TYPE_PTR;
6524 result->this_arg.type = result->byval_arg.type;
6525 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6526 result->this_arg.byref = TRUE;
6528 mono_class_setup_supertypes (result);
6530 mono_image_lock (image);
6531 if (image->ptr_cache) {
6533 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6534 mono_image_unlock (image);
6535 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6539 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6541 g_hash_table_insert (image->ptr_cache, el_class, result);
6542 mono_image_unlock (image);
6544 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6550 mono_fnptr_class_get (MonoMethodSignature *sig)
6553 static GHashTable *ptr_hash = NULL;
6555 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6557 mono_loader_lock ();
6560 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6562 if ((result = (MonoClass *)g_hash_table_lookup (ptr_hash, sig))) {
6563 mono_loader_unlock ();
6566 result = g_new0 (MonoClass, 1);
6568 classes_size += sizeof (MonoClassPointer);
6569 ++class_pointer_count;
6571 result->parent = NULL; /* no parent for PTR types */
6572 result->name_space = "System";
6573 result->name = "MonoFNPtrFakeClass";
6574 result->class_kind = MONO_CLASS_POINTER;
6576 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6578 result->image = mono_defaults.corlib; /* need to fix... */
6579 result->inited = TRUE;
6580 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6581 result->cast_class = result->element_class = result;
6582 result->blittable = TRUE;
6584 result->byval_arg.type = MONO_TYPE_FNPTR;
6585 result->this_arg.type = result->byval_arg.type;
6586 result->this_arg.data.method = result->byval_arg.data.method = sig;
6587 result->this_arg.byref = TRUE;
6588 result->blittable = TRUE;
6590 mono_class_setup_supertypes (result);
6592 g_hash_table_insert (ptr_hash, sig, result);
6594 mono_loader_unlock ();
6596 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6602 * mono_class_from_mono_type:
6603 * @type: describes the type to return
6605 * This returns a MonoClass for the specified MonoType, the value is never NULL.
6608 mono_class_from_mono_type (MonoType *type)
6610 switch (type->type) {
6611 case MONO_TYPE_OBJECT:
6612 return type->data.klass? type->data.klass: mono_defaults.object_class;
6613 case MONO_TYPE_VOID:
6614 return type->data.klass? type->data.klass: mono_defaults.void_class;
6615 case MONO_TYPE_BOOLEAN:
6616 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6617 case MONO_TYPE_CHAR:
6618 return type->data.klass? type->data.klass: mono_defaults.char_class;
6620 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6622 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6624 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6626 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6628 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6630 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6632 return type->data.klass? type->data.klass: mono_defaults.int_class;
6634 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6636 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6638 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6640 return type->data.klass? type->data.klass: mono_defaults.single_class;
6642 return type->data.klass? type->data.klass: mono_defaults.double_class;
6643 case MONO_TYPE_STRING:
6644 return type->data.klass? type->data.klass: mono_defaults.string_class;
6645 case MONO_TYPE_TYPEDBYREF:
6646 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6647 case MONO_TYPE_ARRAY:
6648 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6650 return mono_ptr_class_get (type->data.type);
6651 case MONO_TYPE_FNPTR:
6652 return mono_fnptr_class_get (type->data.method);
6653 case MONO_TYPE_SZARRAY:
6654 return mono_array_class_get (type->data.klass, 1);
6655 case MONO_TYPE_CLASS:
6656 case MONO_TYPE_VALUETYPE:
6657 return type->data.klass;
6658 case MONO_TYPE_GENERICINST:
6659 return mono_generic_class_get_class (type->data.generic_class);
6660 case MONO_TYPE_MVAR:
6662 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6664 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6665 g_assert_not_reached ();
6668 // Yes, this returns NULL, even if it is documented as not doing so, but there
6669 // is no way for the code to make it this far, due to the assert above.
6674 * mono_type_retrieve_from_typespec
6675 * @image: context where the image is created
6676 * @type_spec: typespec token
6677 * @context: the generic context used to evaluate generic instantiations in
6680 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6682 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6684 *did_inflate = FALSE;
6689 if (context && (context->class_inst || context->method_inst)) {
6690 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6692 if (!mono_error_ok (error)) {
6698 *did_inflate = TRUE;
6705 * mono_class_create_from_typespec
6706 * @image: context where the image is created
6707 * @type_spec: typespec token
6708 * @context: the generic context used to evaluate generic instantiations in
6711 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6714 gboolean inflated = FALSE;
6715 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6716 return_val_if_nok (error, NULL);
6717 ret = mono_class_from_mono_type (t);
6719 mono_metadata_free_type (t);
6724 * mono_bounded_array_class_get:
6725 * @element_class: element class
6726 * @rank: the dimension of the array class
6727 * @bounded: whenever the array has non-zero bounds
6729 * Returns: A class object describing the array with element type @element_type and
6733 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6737 MonoClass *parent = NULL;
6738 GSList *list, *rootlist = NULL;
6742 g_assert (rank <= 255);
6745 /* bounded only matters for one-dimensional arrays */
6748 image = eclass->image;
6750 if (rank == 1 && !bounded) {
6752 * This case is very frequent not just during compilation because of calls
6753 * from mono_class_from_mono_type (), mono_array_new (),
6754 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6756 mono_os_mutex_lock (&image->szarray_cache_lock);
6757 if (!image->szarray_cache)
6758 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6759 klass = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6760 mono_os_mutex_unlock (&image->szarray_cache_lock);
6764 mono_loader_lock ();
6766 mono_loader_lock ();
6768 if (!image->array_cache)
6769 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6771 if ((rootlist = list = (GSList *)g_hash_table_lookup (image->array_cache, eclass))) {
6772 for (; list; list = list->next) {
6773 klass = (MonoClass *)list->data;
6774 if ((klass->rank == rank) && (klass->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6775 mono_loader_unlock ();
6782 parent = mono_defaults.array_class;
6783 if (!parent->inited)
6784 mono_class_init (parent);
6786 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassArray));
6788 klass->image = image;
6789 klass->name_space = eclass->name_space;
6790 klass->class_kind = MONO_CLASS_ARRAY;
6792 nsize = strlen (eclass->name);
6793 name = (char *)g_malloc (nsize + 2 + rank + 1);
6794 memcpy (name, eclass->name, nsize);
6797 memset (name + nsize + 1, ',', rank - 1);
6799 name [nsize + rank] = '*';
6800 name [nsize + rank + bounded] = ']';
6801 name [nsize + rank + bounded + 1] = 0;
6802 klass->name = mono_image_strdup (image, name);
6805 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6807 classes_size += sizeof (MonoClassArray);
6808 ++class_array_count;
6810 klass->type_token = 0;
6811 klass->parent = parent;
6812 klass->instance_size = mono_class_instance_size (klass->parent);
6814 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6815 /*Arrays of those two types are invalid.*/
6816 MonoError prepared_error;
6817 mono_error_init (&prepared_error);
6818 mono_error_set_invalid_program (&prepared_error, "Arrays of void or System.TypedReference types are invalid.");
6819 mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6820 mono_error_cleanup (&prepared_error);
6821 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6822 guint32 ref_info_handle = mono_class_get_ref_info_handle (eclass);
6823 if (!ref_info_handle || eclass->wastypebuilder) {
6824 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6825 g_assert (ref_info_handle && !eclass->wastypebuilder);
6827 /* element_size -1 is ok as this is not an instantitable type*/
6828 klass->sizes.element_size = -1;
6830 klass->sizes.element_size = mono_class_array_element_size (eclass);
6832 mono_class_setup_supertypes (klass);
6834 if (mono_class_is_ginst (eclass))
6835 mono_class_init (eclass);
6836 if (!eclass->size_inited)
6837 mono_class_setup_fields (eclass);
6838 mono_class_set_type_load_failure_causedby_class (klass, eclass, "Could not load array element type");
6839 /*FIXME we fail the array type, but we have to let other fields be set.*/
6841 klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6845 if (eclass->enumtype)
6846 klass->cast_class = eclass->element_class;
6848 klass->cast_class = eclass;
6850 switch (klass->cast_class->byval_arg.type) {
6852 klass->cast_class = mono_defaults.byte_class;
6855 klass->cast_class = mono_defaults.int16_class;
6858 #if SIZEOF_VOID_P == 4
6862 klass->cast_class = mono_defaults.int32_class;
6865 #if SIZEOF_VOID_P == 8
6869 klass->cast_class = mono_defaults.int64_class;
6875 klass->element_class = eclass;
6877 if ((rank > 1) || bounded) {
6878 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6879 klass->byval_arg.type = MONO_TYPE_ARRAY;
6880 klass->byval_arg.data.array = at;
6881 at->eklass = eclass;
6883 /* FIXME: complete.... */
6885 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6886 klass->byval_arg.data.klass = eclass;
6888 klass->this_arg = klass->byval_arg;
6889 klass->this_arg.byref = 1;
6891 //WTF was this? it's wrong
6892 // klass->generic_container = eclass->generic_container;
6894 if (rank == 1 && !bounded) {
6895 MonoClass *prev_class;
6897 mono_os_mutex_lock (&image->szarray_cache_lock);
6898 prev_class = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6900 /* Someone got in before us */
6903 g_hash_table_insert (image->szarray_cache, eclass, klass);
6904 mono_os_mutex_unlock (&image->szarray_cache_lock);
6906 list = g_slist_append (rootlist, klass);
6907 g_hash_table_insert (image->array_cache, eclass, list);
6910 mono_loader_unlock ();
6912 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6918 * mono_array_class_get:
6919 * @element_class: element class
6920 * @rank: the dimension of the array class
6922 * Returns: A class object describing the array with element type @element_type and
6926 mono_array_class_get (MonoClass *eclass, guint32 rank)
6928 return mono_bounded_array_class_get (eclass, rank, FALSE);
6932 * mono_class_instance_size:
6935 * Use to get the size of a class in bytes.
6937 * Returns: The size of an object instance
6940 mono_class_instance_size (MonoClass *klass)
6942 if (!klass->size_inited)
6943 mono_class_init (klass);
6945 return klass->instance_size;
6949 * mono_class_min_align:
6952 * Use to get the computed minimum alignment requirements for the specified class.
6954 * Returns: minimum alignment requirements
6957 mono_class_min_align (MonoClass *klass)
6959 if (!klass->size_inited)
6960 mono_class_init (klass);
6962 return klass->min_align;
6966 * mono_class_value_size:
6969 * This function is used for value types, and return the
6970 * space and the alignment to store that kind of value object.
6972 * Returns: the size of a value of kind @klass
6975 mono_class_value_size (MonoClass *klass, guint32 *align)
6979 /* fixme: check disable, because we still have external revereces to
6980 * mscorlib and Dummy Objects
6982 /*g_assert (klass->valuetype);*/
6984 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6987 *align = klass->min_align;
6993 * mono_class_data_size:
6996 * Returns: The size of the static class data
6999 mono_class_data_size (MonoClass *klass)
7002 mono_class_init (klass);
7003 /* This can happen with dynamically created types */
7004 if (!klass->fields_inited)
7005 mono_class_setup_fields (klass);
7007 /* in arrays, sizes.class_size is unioned with element_size
7008 * and arrays have no static fields
7012 return klass->sizes.class_size;
7016 * Auxiliary routine to mono_class_get_field
7018 * Takes a field index instead of a field token.
7020 static MonoClassField *
7021 mono_class_get_field_idx (MonoClass *klass, int idx)
7023 mono_class_setup_fields (klass);
7024 if (mono_class_has_failure (klass))
7028 int first_field_idx = mono_class_get_first_field_idx (klass);
7029 int fcount = mono_class_get_field_count (klass);
7030 if (klass->image->uncompressed_metadata) {
7032 * first_field_idx points to the FieldPtr table, while idx points into the
7033 * Field table, so we have to do a search.
7035 /*FIXME this is broken for types with multiple fields with the same name.*/
7036 const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
7039 for (i = 0; i < fcount; ++i)
7040 if (mono_field_get_name (&klass->fields [i]) == name)
7041 return &klass->fields [i];
7042 g_assert_not_reached ();
7045 if ((idx >= first_field_idx) && (idx < first_field_idx + fcount)){
7046 return &klass->fields [idx - first_field_idx];
7050 klass = klass->parent;
7056 * mono_class_get_field:
7057 * @class: the class to lookup the field.
7058 * @field_token: the field token
7060 * Returns: A MonoClassField representing the type and offset of
7061 * the field, or a NULL value if the field does not belong to this
7065 mono_class_get_field (MonoClass *klass, guint32 field_token)
7067 int idx = mono_metadata_token_index (field_token);
7069 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
7071 return mono_class_get_field_idx (klass, idx - 1);
7075 * mono_class_get_field_from_name:
7076 * @klass: the class to lookup the field.
7077 * @name: the field name
7079 * Search the class @klass and it's parents for a field with the name @name.
7081 * Returns: The MonoClassField pointer of the named field or NULL
7084 mono_class_get_field_from_name (MonoClass *klass, const char *name)
7086 return mono_class_get_field_from_name_full (klass, name, NULL);
7090 * mono_class_get_field_from_name_full:
7091 * @klass: the class to lookup the field.
7092 * @name: the field name
7093 * @type: the type of the fields. This optional.
7095 * Search the class @klass and it's parents for a field with the name @name and type @type.
7097 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
7098 * of its generic type definition.
7100 * Returns: The MonoClassField pointer of the named field or NULL
7103 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
7107 mono_class_setup_fields (klass);
7108 if (mono_class_has_failure (klass))
7112 int fcount = mono_class_get_field_count (klass);
7113 for (i = 0; i < fcount; ++i) {
7114 MonoClassField *field = &klass->fields [i];
7116 if (strcmp (name, mono_field_get_name (field)) != 0)
7120 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
7121 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
7126 klass = klass->parent;
7132 * mono_class_get_field_token:
7133 * @field: the field we need the token of
7135 * Get the token of a field. Note that the tokesn is only valid for the image
7136 * the field was loaded from. Don't use this function for fields in dynamic types.
7138 * Returns: The token representing the field in the image it was loaded from.
7141 mono_class_get_field_token (MonoClassField *field)
7143 MonoClass *klass = field->parent;
7146 mono_class_setup_fields (klass);
7151 int first_field_idx = mono_class_get_first_field_idx (klass);
7152 int fcount = mono_class_get_field_count (klass);
7153 for (i = 0; i < fcount; ++i) {
7154 if (&klass->fields [i] == field) {
7155 int idx = first_field_idx + i + 1;
7157 if (klass->image->uncompressed_metadata)
7158 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
7159 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
7162 klass = klass->parent;
7165 g_assert_not_reached ();
7170 mono_field_get_index (MonoClassField *field)
7172 int index = field - field->parent->fields;
7173 g_assert (index >= 0 && index < mono_class_get_field_count (field->parent));
7179 * mono_class_get_field_default_value:
7181 * Return the default value of the field as a pointer into the metadata blob.
7184 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
7187 guint32 constant_cols [MONO_CONSTANT_SIZE];
7189 MonoClass *klass = field->parent;
7191 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7193 MonoClassExt *ext = mono_class_get_ext (klass);
7194 if (!ext || !ext->field_def_values) {
7195 MonoFieldDefaultValue *def_values;
7197 mono_class_alloc_ext (klass);
7198 ext = mono_class_get_ext (klass);
7200 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
7202 mono_image_lock (klass->image);
7203 mono_memory_barrier ();
7204 if (!ext->field_def_values)
7205 ext->field_def_values = def_values;
7206 mono_image_unlock (klass->image);
7209 field_index = mono_field_get_index (field);
7211 if (!ext->field_def_values [field_index].data) {
7212 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7216 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7218 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7219 ext->field_def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7220 ext->field_def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7223 *def_type = ext->field_def_values [field_index].def_type;
7224 return ext->field_def_values [field_index].data;
7228 mono_property_get_index (MonoProperty *prop)
7230 MonoClassExt *ext = mono_class_get_ext (prop->parent);
7231 int index = prop - ext->properties;
7233 g_assert (index >= 0 && index < ext->property.count);
7239 * mono_class_get_property_default_value:
7241 * Return the default value of the field as a pointer into the metadata blob.
7244 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7247 guint32 constant_cols [MONO_CONSTANT_SIZE];
7248 MonoClass *klass = property->parent;
7250 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7252 * We don't cache here because it is not used by C# so it's quite rare, but
7253 * we still do the lookup in klass->ext because that is where the data
7254 * is stored for dynamic assemblies.
7257 if (image_is_dynamic (klass->image)) {
7258 MonoClassExt *ext = mono_class_get_ext (klass);
7259 int prop_index = mono_property_get_index (property);
7260 if (ext->prop_def_values && ext->prop_def_values [prop_index].data) {
7261 *def_type = ext->prop_def_values [prop_index].def_type;
7262 return ext->prop_def_values [prop_index].data;
7266 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7270 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7271 *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7272 return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7276 mono_class_get_event_token (MonoEvent *event)
7278 MonoClass *klass = event->parent;
7282 MonoClassExt *ext = mono_class_get_ext (klass);
7284 for (i = 0; i < ext->event.count; ++i) {
7285 if (&ext->events [i] == event)
7286 return mono_metadata_make_token (MONO_TABLE_EVENT, ext->event.first + i + 1);
7289 klass = klass->parent;
7292 g_assert_not_reached ();
7297 * mono_class_get_property_from_name:
7299 * @name: name of the property to lookup in the specified class
7301 * Use this method to lookup a property in a class
7302 * Returns: the MonoProperty with the given name, or NULL if the property
7303 * does not exist on the @klass.
7306 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7310 gpointer iter = NULL;
7311 while ((p = mono_class_get_properties (klass, &iter))) {
7312 if (! strcmp (name, p->name))
7315 klass = klass->parent;
7321 * mono_class_get_property_token:
7322 * @prop: MonoProperty to query
7324 * Returns: The ECMA token for the specified property.
7327 mono_class_get_property_token (MonoProperty *prop)
7329 MonoClass *klass = prop->parent;
7333 gpointer iter = NULL;
7334 MonoClassExt *ext = mono_class_get_ext (klass);
7335 while ((p = mono_class_get_properties (klass, &iter))) {
7336 if (&ext->properties [i] == prop)
7337 return mono_metadata_make_token (MONO_TABLE_PROPERTY, ext->property.first + i + 1);
7341 klass = klass->parent;
7344 g_assert_not_reached ();
7349 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7351 const char *name, *nspace;
7352 if (image_is_dynamic (image))
7353 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7355 switch (type_token & 0xff000000){
7356 case MONO_TOKEN_TYPE_DEF: {
7357 guint32 cols [MONO_TYPEDEF_SIZE];
7358 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7359 guint tidx = mono_metadata_token_index (type_token);
7361 if (tidx > tt->rows)
7362 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7364 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7365 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7366 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7367 if (strlen (nspace) == 0)
7368 return g_strdup_printf ("%s", name);
7370 return g_strdup_printf ("%s.%s", nspace, name);
7373 case MONO_TOKEN_TYPE_REF: {
7375 guint32 cols [MONO_TYPEREF_SIZE];
7376 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7377 guint tidx = mono_metadata_token_index (type_token);
7380 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7382 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7383 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7384 mono_error_cleanup (&error);
7388 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7389 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7390 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7391 if (strlen (nspace) == 0)
7392 return g_strdup_printf ("%s", name);
7394 return g_strdup_printf ("%s.%s", nspace, name);
7397 case MONO_TOKEN_TYPE_SPEC:
7398 return g_strdup_printf ("Typespec 0x%08x", type_token);
7400 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7405 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7407 if (image_is_dynamic (image))
7408 return g_strdup_printf ("DynamicAssembly %s", image->name);
7410 switch (type_token & 0xff000000){
7411 case MONO_TOKEN_TYPE_DEF:
7412 if (image->assembly)
7413 return mono_stringify_assembly_name (&image->assembly->aname);
7414 else if (image->assembly_name)
7415 return g_strdup (image->assembly_name);
7416 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7417 case MONO_TOKEN_TYPE_REF: {
7419 MonoAssemblyName aname;
7420 guint32 cols [MONO_TYPEREF_SIZE];
7421 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7422 guint32 idx = mono_metadata_token_index (type_token);
7425 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7427 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7428 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7429 mono_error_cleanup (&error);
7432 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7434 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7435 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7436 case MONO_RESOLUTION_SCOPE_MODULE:
7438 return g_strdup ("");
7439 case MONO_RESOLUTION_SCOPE_MODULEREF:
7441 return g_strdup ("");
7442 case MONO_RESOLUTION_SCOPE_TYPEREF:
7444 return g_strdup ("");
7445 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7446 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7447 return mono_stringify_assembly_name (&aname);
7449 g_assert_not_reached ();
7453 case MONO_TOKEN_TYPE_SPEC:
7455 return g_strdup ("");
7457 g_assert_not_reached ();
7464 * mono_class_get_full:
7465 * @image: the image where the class resides
7466 * @type_token: the token for the class
7467 * @context: the generic context used to evaluate generic instantiations in
7468 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7470 * Returns: The MonoClass that represents @type_token in @image
7473 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7477 klass = mono_class_get_checked (image, type_token, &error);
7479 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7480 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7482 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7488 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7492 mono_error_init (error);
7493 klass = mono_class_get_checked (image, type_token, error);
7495 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7496 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7501 * mono_class_get_checked:
7502 * @image: the image where the class resides
7503 * @type_token: the token for the class
7504 * @error: error object to return any error
7506 * Returns: The MonoClass that represents @type_token in @image, or NULL on error.
7509 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7511 MonoClass *klass = NULL;
7513 mono_error_init (error);
7515 if (image_is_dynamic (image)) {
7516 int table = mono_metadata_token_table (type_token);
7518 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7519 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7522 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
7526 switch (type_token & 0xff000000){
7527 case MONO_TOKEN_TYPE_DEF:
7528 klass = mono_class_create_from_typedef (image, type_token, error);
7530 case MONO_TOKEN_TYPE_REF:
7531 klass = mono_class_from_typeref_checked (image, type_token, error);
7533 case MONO_TOKEN_TYPE_SPEC:
7534 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7537 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7541 /* Generic case, should be avoided for when a better error is possible. */
7542 if (!klass && mono_error_ok (error)) {
7543 char *name = mono_class_name_from_token (image, type_token);
7544 char *assembly = mono_assembly_name_from_token (image, type_token);
7545 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7553 * mono_type_get_checked:
7554 * @image: the image where the type resides
7555 * @type_token: the token for the type
7556 * @context: the generic context used to evaluate generic instantiations in
7557 * @error: Error handling context
7559 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7561 * Returns: The MonoType that represents @type_token in @image
7564 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7566 MonoType *type = NULL;
7567 gboolean inflated = FALSE;
7569 mono_error_init (error);
7571 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7572 if (image_is_dynamic (image)) {
7573 MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
7574 return_val_if_nok (error, NULL);
7575 return mono_class_get_type (klass);
7578 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7579 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7586 return mono_class_get_type (klass);
7589 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7596 MonoType *tmp = type;
7597 type = mono_class_get_type (mono_class_from_mono_type (type));
7598 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7599 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7600 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7602 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7604 if (type->type != tmp->type)
7607 mono_metadata_free_type (tmp);
7614 * @image: image where the class token will be looked up.
7615 * @type_token: a type token from the image
7617 * Returns the MonoClass with the given @type_token on the @image
7620 mono_class_get (MonoImage *image, guint32 type_token)
7622 return mono_class_get_full (image, type_token, NULL);
7626 * mono_image_init_name_cache:
7628 * Initializes the class name cache stored in image->name_cache.
7630 * LOCKING: Acquires the corresponding image lock.
7633 mono_image_init_name_cache (MonoImage *image)
7635 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7636 guint32 cols [MONO_TYPEDEF_SIZE];
7639 guint32 i, visib, nspace_index;
7640 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7642 if (image->name_cache)
7645 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7647 if (image_is_dynamic (image)) {
7648 mono_image_lock (image);
7649 if (image->name_cache) {
7650 /* Somebody initialized it before us */
7651 g_hash_table_destroy (the_name_cache);
7653 mono_atomic_store_release (&image->name_cache, the_name_cache);
7655 mono_image_unlock (image);
7659 /* Temporary hash table to avoid lookups in the nspace_table */
7660 name_cache2 = g_hash_table_new (NULL, NULL);
7662 for (i = 1; i <= t->rows; ++i) {
7663 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7664 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7666 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7667 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7669 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7671 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7672 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7674 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7675 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7676 if (!nspace_table) {
7677 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7678 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7679 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7682 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7685 /* Load type names from EXPORTEDTYPES table */
7687 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7688 guint32 cols [MONO_EXP_TYPE_SIZE];
7691 for (i = 0; i < t->rows; ++i) {
7692 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7694 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7695 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7699 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7700 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7702 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7703 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7704 if (!nspace_table) {
7705 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7706 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7707 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7710 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7714 g_hash_table_destroy (name_cache2);
7716 mono_image_lock (image);
7717 if (image->name_cache) {
7718 /* Somebody initialized it before us */
7719 g_hash_table_destroy (the_name_cache);
7721 mono_atomic_store_release (&image->name_cache, the_name_cache);
7723 mono_image_unlock (image);
7726 /*FIXME Only dynamic assemblies should allow this operation.*/
7728 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7729 const char *name, guint32 index)
7731 GHashTable *nspace_table;
7732 GHashTable *name_cache;
7735 mono_image_init_name_cache (image);
7736 mono_image_lock (image);
7738 name_cache = image->name_cache;
7739 if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7740 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7741 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7744 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7745 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7747 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7749 mono_image_unlock (image);
7758 find_nocase (gpointer key, gpointer value, gpointer user_data)
7760 char *name = (char*)key;
7761 FindUserData *data = (FindUserData*)user_data;
7763 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7764 data->value = value;
7768 * mono_class_from_name_case:
7769 * @image: The MonoImage where the type is looked up in
7770 * @name_space: the type namespace
7771 * @name: the type short name.
7772 * @deprecated: use the mono_class_from_name_case_checked variant instead.
7774 * Obtains a MonoClass with a given namespace and a given name which
7775 * is located in the given MonoImage. The namespace and name
7776 * lookups are case insensitive.
7779 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7782 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7783 mono_error_cleanup (&error);
7789 * mono_class_from_name_case:
7790 * @image: The MonoImage where the type is looked up in
7791 * @name_space: the type namespace
7792 * @name: the type short name.
7795 * Obtains a MonoClass with a given namespace and a given name which
7796 * is located in the given MonoImage. The namespace and name
7797 * lookups are case insensitive.
7799 * Returns: The MonoClass if the given namespace and name were found, or NULL if it
7800 * was not found. The @error object will contain information about the problem
7804 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7806 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7807 guint32 cols [MONO_TYPEDEF_SIZE];
7812 mono_error_init (error);
7814 if (image_is_dynamic (image)) {
7816 FindUserData user_data;
7818 mono_image_init_name_cache (image);
7819 mono_image_lock (image);
7821 user_data.key = name_space;
7822 user_data.value = NULL;
7823 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7825 if (user_data.value) {
7826 GHashTable *nspace_table = (GHashTable*)user_data.value;
7828 user_data.key = name;
7829 user_data.value = NULL;
7831 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7833 if (user_data.value)
7834 token = GPOINTER_TO_UINT (user_data.value);
7837 mono_image_unlock (image);
7840 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7846 /* add a cache if needed */
7847 for (i = 1; i <= t->rows; ++i) {
7848 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7849 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7851 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7852 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7854 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7856 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7857 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7858 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7859 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7865 return_nested_in (MonoClass *klass, char *nested)
7868 char *s = strchr (nested, '/');
7869 gpointer iter = NULL;
7876 while ((found = mono_class_get_nested_types (klass, &iter))) {
7877 if (strcmp (found->name, nested) == 0) {
7879 return return_nested_in (found, s);
7887 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7889 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7890 MonoImage *file_image;
7894 mono_error_init (error);
7897 * The EXPORTEDTYPES table only contains public types, so have to search the
7899 * Note: image->modules contains the contents of the MODULEREF table, while
7900 * the real module list is in the FILE table.
7902 for (i = 0; i < file_table->rows; i++) {
7903 guint32 cols [MONO_FILE_SIZE];
7904 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7905 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7908 file_image = mono_image_load_file_for_image_checked (image, i + 1, error);
7910 klass = mono_class_from_name_checked (file_image, name_space, name, error);
7911 if (klass || !is_ok (error))
7920 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7922 GHashTable *nspace_table;
7923 MonoImage *loaded_image;
7930 mono_error_init (error);
7932 // Checking visited images avoids stack overflows when cyclic references exist.
7933 if (g_hash_table_lookup (visited_images, image))
7936 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7938 if ((nested = strchr (name, '/'))) {
7939 int pos = nested - name;
7940 int len = strlen (name);
7943 memcpy (buf, name, len + 1);
7945 nested = buf + pos + 1;
7949 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7950 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7951 gboolean res = get_class_from_name (image, name_space, name, &klass);
7954 klass = search_modules (image, name_space, name, error);
7959 return klass ? return_nested_in (klass, nested) : NULL;
7965 mono_image_init_name_cache (image);
7966 mono_image_lock (image);
7968 nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7971 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7973 mono_image_unlock (image);
7975 if (!token && image_is_dynamic (image) && image->modules) {
7976 /* Search modules as well */
7977 for (i = 0; i < image->module_count; ++i) {
7978 MonoImage *module = image->modules [i];
7980 klass = mono_class_from_name_checked (module, name_space, name, error);
7981 if (klass || !is_ok (error))
7987 klass = search_modules (image, name_space, name, error);
7988 if (klass || !is_ok (error))
7993 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7994 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7995 guint32 cols [MONO_EXP_TYPE_SIZE];
7998 idx = mono_metadata_token_index (token);
8000 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
8002 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
8003 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
8004 loaded_image = mono_assembly_load_module_checked (image->assembly, impl >> MONO_IMPLEMENTATION_BITS, error);
8007 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
8009 return klass ? return_nested_in (klass, nested) : NULL;
8011 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
8012 guint32 assembly_idx;
8014 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
8016 mono_assembly_load_reference (image, assembly_idx - 1);
8017 g_assert (image->references [assembly_idx - 1]);
8018 if (image->references [assembly_idx - 1] == (gpointer)-1)
8020 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
8022 return klass ? return_nested_in (klass, nested) : NULL;
8025 g_assert_not_reached ();
8029 token = MONO_TOKEN_TYPE_DEF | token;
8031 klass = mono_class_get_checked (image, token, error);
8033 return return_nested_in (klass, nested);
8038 * mono_class_from_name_checked:
8039 * @image: The MonoImage where the type is looked up in
8040 * @name_space: the type namespace
8041 * @name: the type short name.
8043 * Obtains a MonoClass with a given namespace and a given name which
8044 * is located in the given MonoImage.
8046 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
8047 * set if the class was not found or it will return NULL and set the error if there was a loading error.
8050 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
8053 GHashTable *visited_images;
8055 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
8057 klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
8059 g_hash_table_destroy (visited_images);
8065 * mono_class_from_name:
8066 * @image: The MonoImage where the type is looked up in
8067 * @name_space: the type namespace
8068 * @name: the type short name.
8070 * Obtains a MonoClass with a given namespace and a given name which
8071 * is located in the given MonoImage.
8073 * To reference nested classes, use the "/" character as a separator.
8074 * For example use "Foo/Bar" to reference the class Bar that is nested
8075 * inside Foo, like this: "class Foo { class Bar {} }".
8078 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
8083 klass = mono_class_from_name_checked (image, name_space, name, &error);
8084 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
8090 * mono_class_load_from_name:
8091 * @image: The MonoImage where the type is looked up in
8092 * @name_space: the type namespace
8093 * @name: the type short name.
8095 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
8096 * This function should be used by the runtime for critical types to which there's no way to recover but crash
8097 * If they are missing. Thing of System.Object or System.String.
8100 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
8105 klass = mono_class_from_name_checked (image, name_space, name, &error);
8107 g_error ("Runtime critical type %s.%s not found", name_space, name);
8108 if (!mono_error_ok (&error))
8109 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8114 * mono_class_try_load_from_name:
8115 * @image: The MonoImage where the type is looked up in
8116 * @name_space: the type namespace
8117 * @name: the type short name.
8119 * This function tries to load a type, returning the class was found or NULL otherwise.
8120 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
8122 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
8123 * a type that we would otherwise assume to be available but was not due some error.
8127 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
8132 klass = mono_class_from_name_checked (image, name_space, name, &error);
8133 if (!mono_error_ok (&error))
8134 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8140 * mono_class_is_subclass_of:
8141 * @klass: class to probe if it is a subclass of another one
8142 * @klassc: the class we suspect is the base class
8143 * @check_interfaces: whether we should perform interface checks
8145 * This method determines whether @klass is a subclass of @klassc.
8147 * If the @check_interfaces flag is set, then if @klassc is an interface
8148 * this method return TRUE if the @klass implements the interface or
8149 * if @klass is an interface, if one of its base classes is @klass.
8151 * If @check_interfaces is false then, then if @klass is not an interface
8152 * then it returns TRUE if the @klass is a subclass of @klassc.
8154 * if @klass is an interface and @klassc is System.Object, then this function
8159 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
8160 gboolean check_interfaces)
8162 /* FIXME test for interfaces with variant generic arguments */
8163 mono_class_init (klass);
8164 mono_class_init (klassc);
8166 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
8167 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
8169 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
8172 for (i = 0; i < klass->interface_count; i ++) {
8173 MonoClass *ic = klass->interfaces [i];
8178 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
8183 * MS.NET thinks interfaces are a subclass of Object, so we think it as
8186 if (klassc == mono_defaults.object_class)
8193 mono_type_is_generic_argument (MonoType *type)
8195 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
8199 mono_class_has_variant_generic_params (MonoClass *klass)
8202 MonoGenericContainer *container;
8204 if (!mono_class_is_ginst (klass))
8207 container = mono_class_get_generic_container (mono_class_get_generic_class (klass)->container_class);
8209 for (i = 0; i < container->type_argc; ++i)
8210 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8217 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8219 if (target == candidate)
8222 if (check_for_reference_conv &&
8223 mono_type_is_generic_argument (&target->byval_arg) &&
8224 mono_type_is_generic_argument (&candidate->byval_arg)) {
8225 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8226 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8228 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8231 if (!mono_class_is_assignable_from (target, candidate))
8237 * @container the generic container from the GTD
8238 * @klass: the class to be assigned to
8239 * @oklass: the source class
8241 * Both @klass and @oklass must be instances of the same generic interface.
8243 * Returns: TRUE if @klass can be assigned to a @klass variable
8246 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8249 MonoType **klass_argv, **oklass_argv;
8250 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8251 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8253 if (klass == oklass)
8256 /*Viable candidates are instances of the same generic interface*/
8257 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8260 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8261 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8263 for (j = 0; j < container->type_argc; ++j) {
8264 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8265 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8267 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8271 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8272 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8274 if (param1_class != param2_class) {
8275 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8276 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8278 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8279 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8289 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8291 MonoGenericParam *gparam, *ogparam;
8292 MonoGenericParamInfo *tinfo, *cinfo;
8293 MonoClass **candidate_class;
8294 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8297 if (target == candidate)
8299 if (target->byval_arg.type != candidate->byval_arg.type)
8302 gparam = target->byval_arg.data.generic_param;
8303 ogparam = candidate->byval_arg.data.generic_param;
8304 tinfo = mono_generic_param_info (gparam);
8305 cinfo = mono_generic_param_info (ogparam);
8307 class_constraint_satisfied = FALSE;
8308 valuetype_constraint_satisfied = FALSE;
8310 /*candidate must have a super set of target's special constraints*/
8311 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8312 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8314 if (cinfo->constraints) {
8315 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8316 MonoClass *cc = *candidate_class;
8318 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8319 class_constraint_satisfied = TRUE;
8320 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8321 valuetype_constraint_satisfied = TRUE;
8324 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8325 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8327 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8329 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8331 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8332 valuetype_constraint_satisfied)) {
8337 /*candidate type constraints must be a superset of target's*/
8338 if (tinfo->constraints) {
8339 MonoClass **target_class;
8340 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8341 MonoClass *tc = *target_class;
8344 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8345 * check it's constraints since it satisfy the constraint by itself.
8347 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8350 if (!cinfo->constraints)
8353 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8354 MonoClass *cc = *candidate_class;
8356 if (mono_class_is_assignable_from (tc, cc))
8360 * This happens when we have the following:
8362 * Bar<K> where K : IFace
8363 * Foo<T, U> where T : U where U : IFace
8365 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8368 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8369 if (mono_gparam_is_assignable_from (target, cc))
8373 if (!*candidate_class)
8378 /*candidate itself must have a constraint that satisfy target*/
8379 if (cinfo->constraints) {
8380 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8381 MonoClass *cc = *candidate_class;
8382 if (mono_class_is_assignable_from (target, cc))
8390 * mono_class_is_assignable_from:
8391 * @klass: the class to be assigned to
8392 * @oklass: the source class
8394 * Returns: TRUE if an instance of object oklass can be assigned to an
8395 * instance of object @klass
8398 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8401 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8403 mono_class_init (klass);
8405 if (!oklass->inited)
8406 mono_class_init (oklass);
8408 if (mono_class_has_failure (klass) || mono_class_has_failure (oklass))
8411 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8412 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8414 return mono_gparam_is_assignable_from (klass, oklass);
8417 if (MONO_CLASS_IS_INTERFACE (klass)) {
8418 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8419 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8420 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8424 for (i = 0; constraints [i]; ++i) {
8425 if (mono_class_is_assignable_from (klass, constraints [i]))
8433 /* interface_offsets might not be set for dynamic classes */
8434 if (mono_class_get_ref_info_handle (oklass) && !oklass->interface_bitmap) {
8436 * oklass might be a generic type parameter but they have
8437 * interface_offsets set.
8439 gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8440 if (!is_ok (&error)) {
8441 mono_error_cleanup (&error);
8446 if (!oklass->interface_bitmap)
8447 /* Happens with generic instances of not-yet created dynamic types */
8449 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8452 if (mono_class_has_variant_generic_params (klass)) {
8454 mono_class_setup_interfaces (oklass, &error);
8455 if (!mono_error_ok (&error)) {
8456 mono_error_cleanup (&error);
8460 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8461 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8462 MonoClass *iface = oklass->interfaces_packed [i];
8464 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8469 } else if (klass->delegate) {
8470 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8472 }else if (klass->rank) {
8473 MonoClass *eclass, *eoclass;
8475 if (oklass->rank != klass->rank)
8478 /* vectors vs. one dimensional arrays */
8479 if (oklass->byval_arg.type != klass->byval_arg.type)
8482 eclass = klass->cast_class;
8483 eoclass = oklass->cast_class;
8486 * a is b does not imply a[] is b[] when a is a valuetype, and
8487 * b is a reference type.
8490 if (eoclass->valuetype) {
8491 if ((eclass == mono_defaults.enum_class) ||
8492 (eclass == mono_defaults.enum_class->parent) ||
8493 (eclass == mono_defaults.object_class))
8497 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8498 } else if (mono_class_is_nullable (klass)) {
8499 if (mono_class_is_nullable (oklass))
8500 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8502 return mono_class_is_assignable_from (klass->cast_class, oklass);
8503 } else if (klass == mono_defaults.object_class)
8506 return mono_class_has_parent (oklass, klass);
8509 /*Check if @oklass is variant compatible with @klass.*/
8511 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8514 MonoType **klass_argv, **oklass_argv;
8515 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8516 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8518 /*Viable candidates are instances of the same generic interface*/
8519 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8522 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8523 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8525 for (j = 0; j < container->type_argc; ++j) {
8526 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8527 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8529 if (param1_class->valuetype != param2_class->valuetype)
8533 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8534 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8536 if (param1_class != param2_class) {
8537 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8538 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8540 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8541 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8549 /*Check if @candidate implements the interface @target*/
8551 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8555 gboolean is_variant = mono_class_has_variant_generic_params (target);
8557 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8558 if (mono_class_is_variant_compatible_slow (target, candidate))
8563 if (candidate == target)
8566 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8567 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8568 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (candidate);
8570 if (tb && tb->interfaces) {
8571 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8572 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8573 MonoClass *iface_class;
8575 /* we can't realize the type here since it can do pretty much anything. */
8578 iface_class = mono_class_from_mono_type (iface->type);
8579 if (iface_class == target)
8581 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8583 if (mono_class_implement_interface_slow (target, iface_class))
8588 /*setup_interfaces don't mono_class_init anything*/
8589 /*FIXME this doesn't handle primitive type arrays.
8590 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8591 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8593 mono_class_setup_interfaces (candidate, &error);
8594 if (!mono_error_ok (&error)) {
8595 mono_error_cleanup (&error);
8599 for (i = 0; i < candidate->interface_count; ++i) {
8600 if (candidate->interfaces [i] == target)
8603 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8606 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8610 candidate = candidate->parent;
8611 } while (candidate);
8617 * Check if @oklass can be assigned to @klass.
8618 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8621 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8623 if (candidate == target)
8625 if (target == mono_defaults.object_class)
8628 if (mono_class_has_parent (candidate, target))
8631 /*If target is not an interface there is no need to check them.*/
8632 if (MONO_CLASS_IS_INTERFACE (target))
8633 return mono_class_implement_interface_slow (target, candidate);
8635 if (target->delegate && mono_class_has_variant_generic_params (target))
8636 return mono_class_is_variant_compatible (target, candidate, FALSE);
8639 MonoClass *eclass, *eoclass;
8641 if (target->rank != candidate->rank)
8644 /* vectors vs. one dimensional arrays */
8645 if (target->byval_arg.type != candidate->byval_arg.type)
8648 eclass = target->cast_class;
8649 eoclass = candidate->cast_class;
8652 * a is b does not imply a[] is b[] when a is a valuetype, and
8653 * b is a reference type.
8656 if (eoclass->valuetype) {
8657 if ((eclass == mono_defaults.enum_class) ||
8658 (eclass == mono_defaults.enum_class->parent) ||
8659 (eclass == mono_defaults.object_class))
8663 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8665 /*FIXME properly handle nullables */
8666 /*FIXME properly handle (M)VAR */
8671 * mono_class_get_cctor:
8672 * @klass: A MonoClass pointer
8674 * Returns: The static constructor of @klass if it exists, NULL otherwise.
8677 mono_class_get_cctor (MonoClass *klass)
8679 MonoCachedClassInfo cached_info;
8681 if (image_is_dynamic (klass->image)) {
8683 * has_cctor is not set for these classes because mono_class_init () is
8686 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8689 if (!klass->has_cctor)
8692 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8694 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8695 if (!mono_error_ok (&error))
8696 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8700 if (mono_class_is_ginst (klass) && !klass->methods)
8701 return mono_class_get_inflated_method (klass, mono_class_get_cctor (mono_class_get_generic_class (klass)->container_class));
8703 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8707 * mono_class_get_finalizer:
8708 * @klass: The MonoClass pointer
8710 * Returns: The finalizer method of @klass if it exists, NULL otherwise.
8713 mono_class_get_finalizer (MonoClass *klass)
8715 MonoCachedClassInfo cached_info;
8718 mono_class_init (klass);
8719 if (!mono_class_has_finalizer (klass))
8722 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8724 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8725 if (!mono_error_ok (&error))
8726 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8729 mono_class_setup_vtable (klass);
8730 return klass->vtable [finalize_slot];
8735 * mono_class_needs_cctor_run:
8736 * @klass: the MonoClass pointer
8737 * @caller: a MonoMethod describing the caller
8739 * Determines whenever the class has a static constructor and whenever it
8740 * needs to be called when executing CALLER.
8743 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8747 method = mono_class_get_cctor (klass);
8749 return (method == caller) ? FALSE : TRUE;
8755 * mono_class_array_element_size:
8758 * Returns: The number of bytes an element of type @klass
8759 * uses when stored into an array.
8762 mono_class_array_element_size (MonoClass *klass)
8764 MonoType *type = &klass->byval_arg;
8767 switch (type->type) {
8770 case MONO_TYPE_BOOLEAN:
8774 case MONO_TYPE_CHAR:
8783 case MONO_TYPE_CLASS:
8784 case MONO_TYPE_STRING:
8785 case MONO_TYPE_OBJECT:
8786 case MONO_TYPE_SZARRAY:
8787 case MONO_TYPE_ARRAY:
8788 return sizeof (gpointer);
8793 case MONO_TYPE_VALUETYPE:
8794 if (type->data.klass->enumtype) {
8795 type = mono_class_enum_basetype (type->data.klass);
8796 klass = klass->element_class;
8799 return mono_class_instance_size (klass) - sizeof (MonoObject);
8800 case MONO_TYPE_GENERICINST:
8801 type = &type->data.generic_class->container_class->byval_arg;
8804 case MONO_TYPE_MVAR: {
8807 return mono_type_size (type, &align);
8809 case MONO_TYPE_VOID:
8813 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8819 * mono_array_element_size:
8820 * @ac: pointer to a #MonoArrayClass
8822 * Returns: The size of single array element.
8825 mono_array_element_size (MonoClass *ac)
8827 g_assert (ac->rank);
8828 return ac->sizes.element_size;
8832 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8833 MonoGenericContext *context)
8836 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8837 g_assert (mono_error_ok (&error));
8842 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8843 MonoGenericContext *context, MonoError *error)
8845 mono_error_init (error);
8847 if (image_is_dynamic (image)) {
8848 MonoClass *tmp_handle_class;
8849 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
8851 mono_error_assert_ok (error);
8852 g_assert (tmp_handle_class);
8854 *handle_class = tmp_handle_class;
8856 if (tmp_handle_class == mono_defaults.typehandle_class)
8857 return &((MonoClass*)obj)->byval_arg;
8862 switch (token & 0xff000000) {
8863 case MONO_TOKEN_TYPE_DEF:
8864 case MONO_TOKEN_TYPE_REF:
8865 case MONO_TOKEN_TYPE_SPEC: {
8868 *handle_class = mono_defaults.typehandle_class;
8869 type = mono_type_get_checked (image, token, context, error);
8873 mono_class_init (mono_class_from_mono_type (type));
8874 /* We return a MonoType* as handle */
8877 case MONO_TOKEN_FIELD_DEF: {
8879 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8881 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8885 *handle_class = mono_defaults.fieldhandle_class;
8886 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8890 mono_class_init (klass);
8891 return mono_class_get_field (klass, token);
8893 case MONO_TOKEN_METHOD_DEF:
8894 case MONO_TOKEN_METHOD_SPEC: {
8896 meth = mono_get_method_checked (image, token, NULL, context, error);
8898 *handle_class = mono_defaults.methodhandle_class;
8904 case MONO_TOKEN_MEMBER_REF: {
8905 guint32 cols [MONO_MEMBERREF_SIZE];
8907 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8908 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8909 mono_metadata_decode_blob_size (sig, &sig);
8910 if (*sig == 0x6) { /* it's a field */
8912 MonoClassField *field;
8913 field = mono_field_from_token_checked (image, token, &klass, context, error);
8915 *handle_class = mono_defaults.fieldhandle_class;
8919 meth = mono_get_method_checked (image, token, NULL, context, error);
8921 *handle_class = mono_defaults.methodhandle_class;
8926 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8932 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
8934 MonoClass *handle_class;
8935 mono_error_init (error);
8936 return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
8940 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
8942 return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
8945 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8948 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8950 get_cached_class_info = func;
8954 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8956 if (!get_cached_class_info)
8959 return get_cached_class_info (klass, res);
8963 mono_install_get_class_from_name (MonoGetClassFromName func)
8965 get_class_from_name = func;
8969 * mono_class_get_image:
8971 * Use this method to get the `MonoImage*` where this class came from.
8973 * Returns: The image where this class is defined.
8976 mono_class_get_image (MonoClass *klass)
8978 return klass->image;
8982 * mono_class_get_element_class:
8983 * @klass: the MonoClass to act on
8985 * Use this function to get the element class of an array.
8987 * Returns: The element class of an array.
8990 mono_class_get_element_class (MonoClass *klass)
8992 return klass->element_class;
8996 * mono_class_is_valuetype:
8997 * @klass: the MonoClass to act on
8999 * Use this method to determine if the provided `MonoClass*` represents a value type,
9000 * or a reference type.
9002 * Returns: TRUE if the MonoClass represents a ValueType, FALSE if it represents a reference type.
9005 mono_class_is_valuetype (MonoClass *klass)
9007 return klass->valuetype;
9011 * mono_class_is_enum:
9012 * @klass: the MonoClass to act on
9014 * Use this function to determine if the provided `MonoClass*` represents an enumeration.
9016 * Returns: TRUE if the MonoClass represents an enumeration.
9019 mono_class_is_enum (MonoClass *klass)
9021 return klass->enumtype;
9025 * mono_class_enum_basetype:
9026 * @klass: the MonoClass to act on
9028 * Use this function to get the underlying type for an enumeration value.
9030 * Returns: The underlying type representation for an enumeration.
9033 mono_class_enum_basetype (MonoClass *klass)
9035 if (klass->element_class == klass)
9036 /* SRE or broken types */
9039 return &klass->element_class->byval_arg;
9043 * mono_class_get_parent
9044 * @klass: the MonoClass to act on
9046 * Returns: The parent class for this class.
9049 mono_class_get_parent (MonoClass *klass)
9051 return klass->parent;
9055 * mono_class_get_nesting_type:
9056 * @klass: the MonoClass to act on
9058 * Use this function to obtain the class that the provided `MonoClass*` is nested on.
9060 * If the return is NULL, this indicates that this class is not nested.
9062 * Returns: The container type where this type is nested or NULL if this type is not a nested type.
9065 mono_class_get_nesting_type (MonoClass *klass)
9067 return klass->nested_in;
9071 * mono_class_get_rank:
9072 * @klass: the MonoClass to act on
9074 * Returns: The rank for the array (the number of dimensions).
9077 mono_class_get_rank (MonoClass *klass)
9083 * mono_class_get_name
9084 * @klass: the MonoClass to act on
9086 * Returns: The name of the class.
9089 mono_class_get_name (MonoClass *klass)
9095 * mono_class_get_namespace:
9096 * @klass: the MonoClass to act on
9098 * Returns: The namespace of the class.
9101 mono_class_get_namespace (MonoClass *klass)
9103 return klass->name_space;
9107 * mono_class_get_type:
9108 * @klass: the MonoClass to act on
9110 * This method returns the internal Type representation for the class.
9112 * Returns: The MonoType from the class.
9115 mono_class_get_type (MonoClass *klass)
9117 return &klass->byval_arg;
9121 * mono_class_get_type_token:
9122 * @klass: the MonoClass to act on
9124 * This method returns type token for the class.
9126 * Returns: The type token for the class.
9129 mono_class_get_type_token (MonoClass *klass)
9131 return klass->type_token;
9135 * mono_class_get_byref_type:
9136 * @klass: the MonoClass to act on
9141 mono_class_get_byref_type (MonoClass *klass)
9143 return &klass->this_arg;
9147 * mono_class_num_fields:
9148 * @klass: the MonoClass to act on
9150 * Returns: The number of static and instance fields in the class.
9153 mono_class_num_fields (MonoClass *klass)
9155 return mono_class_get_field_count (klass);
9159 * mono_class_num_methods:
9160 * @klass: the MonoClass to act on
9162 * Returns: The number of methods in the class.
9165 mono_class_num_methods (MonoClass *klass)
9167 return mono_class_get_method_count (klass);
9171 * mono_class_num_properties
9172 * @klass: the MonoClass to act on
9174 * Returns: The number of properties in the class.
9177 mono_class_num_properties (MonoClass *klass)
9179 mono_class_setup_properties (klass);
9181 return mono_class_get_ext (klass)->property.count;
9185 * mono_class_num_events:
9186 * @klass: the MonoClass to act on
9188 * Returns: The number of events in the class.
9191 mono_class_num_events (MonoClass *klass)
9193 mono_class_setup_events (klass);
9195 return mono_class_get_ext (klass)->event.count;
9199 * mono_class_get_fields:
9200 * @klass: the MonoClass to act on
9202 * This routine is an iterator routine for retrieving the fields in a class.
9204 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9205 * iterate over all of the elements. When no more values are
9206 * available, the return value is NULL.
9208 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
9211 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9213 MonoClassField* field;
9217 mono_class_setup_fields (klass);
9218 if (mono_class_has_failure (klass))
9220 /* start from the first */
9221 if (mono_class_get_field_count (klass)) {
9222 *iter = &klass->fields [0];
9223 return &klass->fields [0];
9229 field = (MonoClassField *)*iter;
9231 if (field < &klass->fields [mono_class_get_field_count (klass)]) {
9239 * mono_class_get_methods
9240 * @klass: the MonoClass to act on
9242 * This routine is an iterator routine for retrieving the fields in a class.
9244 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9245 * iterate over all of the elements. When no more values are
9246 * available, the return value is NULL.
9248 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
9251 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9253 MonoMethod** method;
9257 mono_class_setup_methods (klass);
9260 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9261 * FIXME we should better report this error to the caller
9263 if (!klass->methods)
9265 /* start from the first */
9266 if (mono_class_get_method_count (klass)) {
9267 *iter = &klass->methods [0];
9268 return klass->methods [0];
9274 method = (MonoMethod **)*iter;
9276 if (method < &klass->methods [mono_class_get_method_count (klass)]) {
9284 * mono_class_get_virtual_methods:
9286 * Iterate over the virtual methods of KLASS.
9288 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9291 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9293 MonoMethod** method;
9296 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9298 mono_class_setup_methods (klass);
9300 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9301 * FIXME we should better report this error to the caller
9303 if (!klass->methods)
9305 /* start from the first */
9306 method = &klass->methods [0];
9308 method = (MonoMethod **)*iter;
9311 int mcount = mono_class_get_method_count (klass);
9312 while (method < &klass->methods [mcount]) {
9313 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9317 if (method < &klass->methods [mcount]) {
9324 /* Search directly in metadata to avoid calling setup_methods () */
9325 MonoMethod *res = NULL;
9331 start_index = GPOINTER_TO_UINT (*iter);
9334 int first_idx = mono_class_get_first_method_idx (klass);
9335 int mcount = mono_class_get_method_count (klass);
9336 for (i = start_index; i < mcount; ++i) {
9339 /* first_idx points into the methodptr table */
9340 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
9342 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9348 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9349 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9351 /* Add 1 here so the if (*iter) check fails */
9352 *iter = GUINT_TO_POINTER (i + 1);
9361 * mono_class_get_properties:
9362 * @klass: the MonoClass to act on
9364 * This routine is an iterator routine for retrieving the properties in a class.
9366 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9367 * iterate over all of the elements. When no more values are
9368 * available, the return value is NULL.
9370 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9373 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9375 MonoProperty* property;
9379 mono_class_setup_properties (klass);
9380 MonoClassExt *ext = mono_class_get_ext (klass);
9381 /* start from the first */
9382 if (ext->property.count) {
9383 *iter = &ext->properties [0];
9384 return (MonoProperty *)*iter;
9390 property = (MonoProperty *)*iter;
9392 MonoClassExt *ext = mono_class_get_ext (klass);
9393 if (property < &ext->properties [ext->property.count]) {
9395 return (MonoProperty *)*iter;
9401 * mono_class_get_events:
9402 * @klass: the MonoClass to act on
9404 * This routine is an iterator routine for retrieving the properties in a class.
9406 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9407 * iterate over all of the elements. When no more values are
9408 * available, the return value is NULL.
9410 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9413 mono_class_get_events (MonoClass* klass, gpointer *iter)
9419 mono_class_setup_events (klass);
9420 MonoClassExt *ext = mono_class_get_ext (klass);
9421 /* start from the first */
9422 if (ext->event.count) {
9423 *iter = &ext->events [0];
9424 return (MonoEvent *)*iter;
9430 event = (MonoEvent *)*iter;
9432 MonoClassExt *ext = mono_class_get_ext (klass);
9433 if (event < &ext->events [ext->event.count]) {
9435 return (MonoEvent *)*iter;
9441 * mono_class_get_interfaces
9442 * @klass: the MonoClass to act on
9444 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9446 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9447 * iterate over all of the elements. When no more values are
9448 * available, the return value is NULL.
9450 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9453 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9461 mono_class_init (klass);
9462 if (!klass->interfaces_inited) {
9463 mono_class_setup_interfaces (klass, &error);
9464 if (!mono_error_ok (&error)) {
9465 mono_error_cleanup (&error);
9469 /* start from the first */
9470 if (klass->interface_count) {
9471 *iter = &klass->interfaces [0];
9472 return klass->interfaces [0];
9478 iface = (MonoClass **)*iter;
9480 if (iface < &klass->interfaces [klass->interface_count]) {
9488 setup_nested_types (MonoClass *klass)
9491 GList *classes, *nested_classes, *l;
9494 if (klass->nested_classes_inited)
9497 if (!klass->type_token)
9498 klass->nested_classes_inited = TRUE;
9500 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9504 guint32 cols [MONO_NESTED_CLASS_SIZE];
9505 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9506 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9507 if (!mono_error_ok (&error)) {
9508 /*FIXME don't swallow the error message*/
9509 mono_error_cleanup (&error);
9511 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9515 classes = g_list_prepend (classes, nclass);
9517 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9520 mono_class_alloc_ext (klass);
9522 nested_classes = NULL;
9523 for (l = classes; l; l = l->next)
9524 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9525 g_list_free (classes);
9527 mono_image_lock (klass->image);
9529 mono_memory_barrier ();
9530 if (!klass->nested_classes_inited) {
9531 mono_class_get_ext (klass)->nested_classes = nested_classes;
9532 mono_memory_barrier ();
9533 klass->nested_classes_inited = TRUE;
9536 mono_image_unlock (klass->image);
9540 * mono_class_get_nested_types
9541 * @klass: the MonoClass to act on
9543 * This routine is an iterator routine for retrieving the nested types of a class.
9544 * This works only if @klass is non-generic, or a generic type definition.
9546 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9547 * iterate over all of the elements. When no more values are
9548 * available, the return value is NULL.
9550 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9553 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9559 if (!klass->nested_classes_inited)
9560 setup_nested_types (klass);
9563 MonoClassExt *ext = mono_class_get_ext (klass);
9564 /* start from the first */
9565 if (ext && ext->nested_classes) {
9566 *iter = ext->nested_classes;
9567 return (MonoClass *)ext->nested_classes->data;
9569 /* no nested types */
9573 item = (GList *)*iter;
9577 return (MonoClass *)item->data;
9584 * mono_class_is_delegate
9585 * @klass: the MonoClass to act on
9587 * Returns: TRUE if the MonoClass represents a System.Delegate.
9590 mono_class_is_delegate (MonoClass *klass)
9592 return klass->delegate;
9596 * mono_class_implements_interface
9597 * @klass: The MonoClass to act on
9598 * @interface: The interface to check if @klass implements.
9600 * Returns: TRUE if @klass implements @interface.
9603 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9605 return mono_class_is_assignable_from (iface, klass);
9609 * mono_field_get_name:
9610 * @field: the MonoClassField to act on
9612 * Returns: The name of the field.
9615 mono_field_get_name (MonoClassField *field)
9621 * mono_field_get_type:
9622 * @field: the MonoClassField to act on
9624 * Returns: MonoType of the field.
9627 mono_field_get_type (MonoClassField *field)
9630 MonoType *type = mono_field_get_type_checked (field, &error);
9631 if (!mono_error_ok (&error)) {
9632 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9633 mono_error_cleanup (&error);
9640 * mono_field_get_type_checked:
9641 * @field: the MonoClassField to act on
9642 * @error: used to return any erro found while retrieving @field type
9644 * Returns: MonoType of the field.
9647 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9649 mono_error_init (error);
9651 mono_field_resolve_type (field, error);
9656 * mono_field_get_parent:
9657 * @field: the MonoClassField to act on
9659 * Returns: MonoClass where the field was defined.
9662 mono_field_get_parent (MonoClassField *field)
9664 return field->parent;
9668 * mono_field_get_flags;
9669 * @field: the MonoClassField to act on
9671 * The metadata flags for a field are encoded using the
9672 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9674 * Returns: The flags for the field.
9677 mono_field_get_flags (MonoClassField *field)
9680 return mono_field_resolve_flags (field);
9681 return field->type->attrs;
9685 * mono_field_get_offset:
9686 * @field: the MonoClassField to act on
9688 * Returns: The field offset.
9691 mono_field_get_offset (MonoClassField *field)
9693 return field->offset;
9697 mono_field_get_rva (MonoClassField *field)
9701 MonoClass *klass = field->parent;
9702 MonoFieldDefaultValue *field_def_values;
9704 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9706 MonoClassExt *ext = mono_class_get_ext (klass);
9707 if (!ext || !ext->field_def_values) {
9708 mono_class_alloc_ext (klass);
9709 ext = mono_class_get_ext (klass);
9711 field_def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
9713 mono_image_lock (klass->image);
9714 if (!ext->field_def_values)
9715 ext->field_def_values = field_def_values;
9716 mono_image_unlock (klass->image);
9719 field_index = mono_field_get_index (field);
9721 if (!ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9722 int first_field_idx = mono_class_get_first_field_idx (klass);
9723 mono_metadata_field_info (field->parent->image, first_field_idx + field_index, NULL, &rva, NULL);
9725 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9726 ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9729 return ext->field_def_values [field_index].data;
9733 * mono_field_get_data:
9734 * @field: the MonoClassField to act on
9736 * Returns: A pointer to the metadata constant value or to the field
9737 * data if it has an RVA flag.
9740 mono_field_get_data (MonoClassField *field)
9742 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9743 MonoTypeEnum def_type;
9745 return mono_class_get_field_default_value (field, &def_type);
9746 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9747 return mono_field_get_rva (field);
9754 * mono_property_get_name:
9755 * @prop: the MonoProperty to act on
9757 * Returns: The name of the property
9760 mono_property_get_name (MonoProperty *prop)
9766 * mono_property_get_set_method
9767 * @prop: the MonoProperty to act on.
9769 * Returns: The setter method of the property (A MonoMethod)
9772 mono_property_get_set_method (MonoProperty *prop)
9778 * mono_property_get_get_method
9779 * @prop: the MonoProperty to act on.
9781 * Returns: The setter method of the property (A MonoMethod)
9784 mono_property_get_get_method (MonoProperty *prop)
9790 * mono_property_get_parent:
9791 * @prop: the MonoProperty to act on.
9793 * Returns: The MonoClass where the property was defined.
9796 mono_property_get_parent (MonoProperty *prop)
9798 return prop->parent;
9802 * mono_property_get_flags:
9803 * @prop: the MonoProperty to act on.
9805 * The metadata flags for a property are encoded using the
9806 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9808 * Returns: The flags for the property.
9811 mono_property_get_flags (MonoProperty *prop)
9817 * mono_event_get_name:
9818 * @event: the MonoEvent to act on
9820 * Returns: The name of the event.
9823 mono_event_get_name (MonoEvent *event)
9829 * mono_event_get_add_method:
9830 * @event: The MonoEvent to act on.
9832 * Returns: The @add' method for the event (a MonoMethod).
9835 mono_event_get_add_method (MonoEvent *event)
9841 * mono_event_get_remove_method:
9842 * @event: The MonoEvent to act on.
9844 * Returns: The @remove method for the event (a MonoMethod).
9847 mono_event_get_remove_method (MonoEvent *event)
9849 return event->remove;
9853 * mono_event_get_raise_method:
9854 * @event: The MonoEvent to act on.
9856 * Returns: The @raise method for the event (a MonoMethod).
9859 mono_event_get_raise_method (MonoEvent *event)
9861 return event->raise;
9865 * mono_event_get_parent:
9866 * @event: the MonoEvent to act on.
9868 * Returns: The MonoClass where the event is defined.
9871 mono_event_get_parent (MonoEvent *event)
9873 return event->parent;
9877 * mono_event_get_flags
9878 * @event: the MonoEvent to act on.
9880 * The metadata flags for an event are encoded using the
9881 * EVENT_* constants. See the tabledefs.h file for details.
9883 * Returns: The flags for the event.
9886 mono_event_get_flags (MonoEvent *event)
9888 return event->attrs;
9892 * mono_class_get_method_from_name:
9893 * @klass: where to look for the method
9894 * @name: name of the method
9895 * @param_count: number of parameters. -1 for any number.
9897 * Obtains a MonoMethod with a given name and number of parameters.
9898 * It only works if there are no multiple signatures for any given method name.
9901 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9903 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9907 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9909 MonoMethod *res = NULL;
9912 /* Search directly in the metadata to avoid calling setup_methods () */
9913 int first_idx = mono_class_get_first_method_idx (klass);
9914 int mcount = mono_class_get_method_count (klass);
9915 for (i = 0; i < mcount; ++i) {
9917 guint32 cols [MONO_METHOD_SIZE];
9919 MonoMethodSignature *sig;
9921 /* first_idx points into the methodptr table */
9922 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, first_idx + i, cols, MONO_METHOD_SIZE);
9924 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9925 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9927 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9930 if (param_count == -1) {
9934 sig = mono_method_signature_checked (method, &error);
9936 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9939 if (sig->param_count == param_count) {
9950 * mono_class_get_method_from_name_flags:
9951 * @klass: where to look for the method
9952 * @name_space: name of the method
9953 * @param_count: number of parameters. -1 for any number.
9954 * @flags: flags which must be set in the method
9956 * Obtains a MonoMethod with a given name and number of parameters.
9957 * It only works if there are no multiple signatures for any given method name.
9960 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9962 MonoMethod *res = NULL;
9965 mono_class_init (klass);
9967 if (mono_class_is_ginst (klass) && !klass->methods) {
9968 res = mono_class_get_method_from_name_flags (mono_class_get_generic_class (klass)->container_class, name, param_count, flags);
9971 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9972 if (!mono_error_ok (&error))
9973 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9978 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9979 mono_class_setup_methods (klass);
9981 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9982 See mono/tests/array_load_exception.il
9983 FIXME we should better report this error to the caller
9985 if (!klass->methods)
9987 int mcount = mono_class_get_method_count (klass);
9988 for (i = 0; i < mcount; ++i) {
9989 MonoMethod *method = klass->methods [i];
9991 if (method->name[0] == name [0] &&
9992 !strcmp (name, method->name) &&
9993 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9994 ((method->flags & flags) == flags)) {
10001 res = find_method_in_metadata (klass, name, param_count, flags);
10008 * mono_class_set_failure:
10009 * @klass: class in which the failure was detected
10010 * @ex_type: the kind of exception/error to be thrown (later)
10011 * @ex_data: exception data (specific to each type of exception/error)
10013 * Keep a detected failure informations in the class for later processing.
10014 * Note that only the first failure is kept.
10016 * LOCKING: Acquires the loader lock.
10019 mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error)
10021 g_assert (boxed_error != NULL);
10023 if (mono_class_has_failure (klass))
10026 mono_loader_lock ();
10027 klass->has_failure = 1;
10028 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, boxed_error);
10029 mono_loader_unlock ();
10035 mono_class_has_failure (const MonoClass *klass)
10037 g_assert (klass != NULL);
10038 return klass->has_failure != 0;
10043 * mono_class_set_type_load_failure:
10044 * @klass: class in which the failure was detected
10045 * @fmt: Printf-style error message string.
10047 * Collect detected failure informaion in the class for later processing.
10048 * The error is stored as a MonoErrorBoxed as with mono_error_set_type_load_class ()
10049 * Note that only the first failure is kept.
10051 * Returns FALSE if a failure was already set on the class, or TRUE otherwise.
10053 * LOCKING: Acquires the loader lock.
10056 mono_class_set_type_load_failure (MonoClass *klass, const char * fmt, ...)
10058 MonoError prepare_error;
10061 if (mono_class_has_failure (klass))
10064 mono_error_init (&prepare_error);
10066 va_start (args, fmt);
10067 mono_error_vset_type_load_class (&prepare_error, klass, fmt, args);
10070 MonoErrorBoxed *box = mono_error_box (&prepare_error, klass->image);
10071 mono_error_cleanup (&prepare_error);
10072 return mono_class_set_failure (klass, box);
10076 * mono_class_get_exception_data:
10078 * Return the exception_data property of KLASS.
10080 * LOCKING: Acquires the loader lock.
10083 mono_class_get_exception_data (const MonoClass *klass)
10085 return mono_image_property_lookup (klass->image, (MonoClass*)klass, MONO_CLASS_PROP_EXCEPTION_DATA);
10089 * mono_classes_init:
10091 * Initialize the resources used by this module.
10094 mono_classes_init (void)
10096 mono_os_mutex_init (&classes_mutex);
10098 mono_native_tls_alloc (&setup_fields_tls_id, NULL);
10099 mono_native_tls_alloc (&init_pending_tls_id, NULL);
10101 mono_counters_register ("MonoClassDef count",
10102 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_def_count);
10103 mono_counters_register ("MonoClassGtd count",
10104 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gtd_count);
10105 mono_counters_register ("MonoClassGenericInst count",
10106 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ginst_count);
10107 mono_counters_register ("MonoClassGenericParam count",
10108 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gparam_count);
10109 mono_counters_register ("MonoClassArray count",
10110 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_array_count);
10111 mono_counters_register ("MonoClassPointer count",
10112 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_pointer_count);
10113 mono_counters_register ("Inflated methods size",
10114 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
10115 mono_counters_register ("Inflated classes size",
10116 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
10117 mono_counters_register ("MonoClass size",
10118 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
10119 mono_counters_register ("MonoClassExt size",
10120 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
10122 mono_counters_register ("MonoClassExt count",
10123 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_count);
10127 * mono_classes_cleanup:
10129 * Free the resources used by this module.
10132 mono_classes_cleanup (void)
10134 mono_native_tls_free (setup_fields_tls_id);
10135 mono_native_tls_free (init_pending_tls_id);
10137 if (global_interface_bitset)
10138 mono_bitset_free (global_interface_bitset);
10139 global_interface_bitset = NULL;
10140 mono_os_mutex_destroy (&classes_mutex);
10144 * mono_class_get_exception_for_failure:
10145 * @klass: class in which the failure was detected
10147 * Return a constructed MonoException than the caller can then throw
10148 * using mono_raise_exception - or NULL if no failure is present (or
10149 * doesn't result in an exception).
10152 mono_class_get_exception_for_failure (MonoClass *klass)
10154 if (!mono_class_has_failure (klass))
10156 MonoError unboxed_error;
10157 mono_error_init (&unboxed_error);
10158 mono_error_set_for_class_failure (&unboxed_error, klass);
10159 return mono_error_convert_to_exception (&unboxed_error);
10163 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
10165 outer_klass = mono_class_get_generic_type_definition (outer_klass);
10166 inner_klass = mono_class_get_generic_type_definition (inner_klass);
10168 if (outer_klass == inner_klass)
10170 inner_klass = inner_klass->nested_in;
10171 } while (inner_klass);
10176 mono_class_get_generic_type_definition (MonoClass *klass)
10178 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
10179 return gklass ? gklass->container_class : klass;
10183 * Check if @klass is a subtype of @parent ignoring generic instantiations.
10185 * Generic instantiations are ignored for all super types of @klass.
10187 * Visibility checks ignoring generic instantiations.
10190 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
10193 klass = mono_class_get_generic_type_definition (klass);
10194 parent = mono_class_get_generic_type_definition (parent);
10195 mono_class_setup_supertypes (klass);
10197 for (i = 0; i < klass->idepth; ++i) {
10198 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
10204 * Subtype can only access parent members with family protection if the site object
10205 * is subclass of Subtype. For example:
10206 * class A { protected int x; }
10208 * void valid_access () {
10212 * void invalid_access () {
10219 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
10221 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
10224 if (context_klass == NULL)
10226 /*if access_klass is not member_klass context_klass must be type compat*/
10227 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10233 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10236 if (accessing == accessed)
10238 if (!accessed || !accessing)
10241 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10242 * anywhere so untrusted friends are not safe to access platform's code internals */
10243 if (mono_security_core_clr_enabled ()) {
10244 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10248 mono_assembly_load_friends (accessed);
10249 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10250 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10251 /* Be conservative with checks */
10252 if (!friend_->name)
10254 if (strcmp (accessing->aname.name, friend_->name))
10256 if (friend_->public_key_token [0]) {
10257 if (!accessing->aname.public_key_token [0])
10259 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10268 * If klass is a generic type or if it is derived from a generic type, return the
10269 * MonoClass of the generic definition
10270 * Returns NULL if not found
10273 get_generic_definition_class (MonoClass *klass)
10276 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
10277 if (gklass && gklass->container_class)
10278 return gklass->container_class;
10279 klass = klass->parent;
10285 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10288 for (i = 0; i < ginst->type_argc; ++i) {
10289 MonoType *type = ginst->type_argv[i];
10290 switch (type->type) {
10291 case MONO_TYPE_SZARRAY:
10292 if (!can_access_type (access_klass, type->data.klass))
10295 case MONO_TYPE_ARRAY:
10296 if (!can_access_type (access_klass, type->data.array->eklass))
10299 case MONO_TYPE_PTR:
10300 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10303 case MONO_TYPE_CLASS:
10304 case MONO_TYPE_VALUETYPE:
10305 case MONO_TYPE_GENERICINST:
10306 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10316 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10320 if (access_klass == member_klass)
10323 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10326 if (access_klass->element_class && !access_klass->enumtype)
10327 access_klass = access_klass->element_class;
10329 if (member_klass->element_class && !member_klass->enumtype)
10330 member_klass = member_klass->element_class;
10332 access_level = mono_class_get_flags (member_klass) & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10334 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10337 if (mono_class_is_ginst (member_klass) && !can_access_instantiation (access_klass, mono_class_get_generic_class (member_klass)->context.class_inst))
10340 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10343 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10346 /*Non nested type with nested visibility. We just fail it.*/
10347 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10350 switch (access_level) {
10351 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10352 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10354 case TYPE_ATTRIBUTE_PUBLIC:
10357 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10360 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10361 return is_nesting_type (member_klass, access_klass);
10363 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10364 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10366 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10367 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10369 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10370 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10371 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10373 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10374 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10375 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10380 /* FIXME: check visibility of type, too */
10382 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10384 MonoClass *member_generic_def;
10385 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10388 MonoGenericClass *access_gklass = mono_class_try_get_generic_class (access_klass);
10389 if (((access_gklass && access_gklass->container_class) ||
10390 mono_class_is_gtd (access_klass)) &&
10391 (member_generic_def = get_generic_definition_class (member_klass))) {
10392 MonoClass *access_container;
10394 if (mono_class_is_gtd (access_klass))
10395 access_container = access_klass;
10397 access_container = access_gklass->container_class;
10399 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10403 /* Partition I 8.5.3.2 */
10404 /* the access level values are the same for fields and methods */
10405 switch (access_level) {
10406 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10407 /* same compilation unit */
10408 return access_klass->image == member_klass->image;
10409 case FIELD_ATTRIBUTE_PRIVATE:
10410 return access_klass == member_klass;
10411 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10412 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10413 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10416 case FIELD_ATTRIBUTE_ASSEMBLY:
10417 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10418 case FIELD_ATTRIBUTE_FAMILY:
10419 if (is_valid_family_access (access_klass, member_klass, context_klass))
10422 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10423 if (is_valid_family_access (access_klass, member_klass, context_klass))
10425 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10426 case FIELD_ATTRIBUTE_PUBLIC:
10433 * mono_method_can_access_field:
10434 * @method: Method that will attempt to access the field
10435 * @field: the field to access
10437 * Used to determine if a method is allowed to access the specified field.
10439 * Returns: TRUE if the given @method is allowed to access the @field while following
10440 * the accessibility rules of the CLI.
10443 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10445 /* FIXME: check all overlapping fields */
10446 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10448 MonoClass *nested = method->klass->nested_in;
10450 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10453 nested = nested->nested_in;
10460 * mono_method_can_access_method:
10461 * @method: Method that will attempt to access the other method
10462 * @called: the method that we want to probe for accessibility.
10464 * Used to determine if the @method is allowed to access the specified @called method.
10466 * Returns: TRUE if the given @method is allowed to invoke the @called while following
10467 * the accessibility rules of the CLI.
10470 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10472 method = mono_method_get_method_definition (method);
10473 called = mono_method_get_method_definition (called);
10474 return mono_method_can_access_method_full (method, called, NULL);
10478 * mono_method_can_access_method_full:
10479 * @method: The caller method
10480 * @called: The called method
10481 * @context_klass: The static type on stack of the owner @called object used
10483 * This function must be used with instance calls, as they have more strict family accessibility.
10484 * It can be used with static methods, but context_klass should be NULL.
10486 * Returns: TRUE if caller have proper visibility and acessibility to @called
10489 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10491 /* Wrappers are except from access checks */
10492 if (method->wrapper_type != MONO_WRAPPER_NONE || called->wrapper_type != MONO_WRAPPER_NONE)
10495 MonoClass *access_class = method->klass;
10496 MonoClass *member_class = called->klass;
10497 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10499 MonoClass *nested = access_class->nested_in;
10501 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10504 nested = nested->nested_in;
10511 can = can_access_type (access_class, member_class);
10513 MonoClass *nested = access_class->nested_in;
10515 can = can_access_type (nested, member_class);
10518 nested = nested->nested_in;
10525 if (called->is_inflated) {
10526 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10527 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10536 * mono_method_can_access_field_full:
10537 * @method: The caller method
10538 * @field: The accessed field
10539 * @context_klass: The static type on stack of the owner @field object used
10541 * This function must be used with instance fields, as they have more strict family accessibility.
10542 * It can be used with static fields, but context_klass should be NULL.
10544 * Returns: TRUE if caller have proper visibility and acessibility to @field
10547 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10549 MonoClass *access_class = method->klass;
10550 MonoClass *member_class = field->parent;
10551 /* FIXME: check all overlapping fields */
10552 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10554 MonoClass *nested = access_class->nested_in;
10556 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10559 nested = nested->nested_in;
10566 can = can_access_type (access_class, member_class);
10568 MonoClass *nested = access_class->nested_in;
10570 can = can_access_type (nested, member_class);
10573 nested = nested->nested_in;
10583 * mono_class_can_access_class:
10584 * @source_class: The source class
10585 * @target_class: The accessed class
10587 * This function returns is @target_class is visible to @source_class
10589 * Returns: TRUE if source have proper visibility and acessibility to target
10592 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10594 return can_access_type (source_class, target_class);
10598 * mono_type_is_valid_enum_basetype:
10599 * @type: The MonoType to check
10601 * Returns: TRUE if the type can be used as the basetype of an enum
10603 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10604 switch (type->type) {
10607 case MONO_TYPE_BOOLEAN:
10610 case MONO_TYPE_CHAR:
10624 * mono_class_is_valid_enum:
10625 * @klass: An enum class to be validated
10627 * This method verify the required properties an enum should have.
10629 * Returns: TRUE if the informed enum class is valid
10631 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10632 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10633 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10636 mono_class_is_valid_enum (MonoClass *klass)
10638 MonoClassField * field;
10639 gpointer iter = NULL;
10640 gboolean found_base_field = FALSE;
10642 g_assert (klass->enumtype);
10643 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10644 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10648 if (!mono_class_is_auto_layout (klass))
10651 while ((field = mono_class_get_fields (klass, &iter))) {
10652 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10653 if (found_base_field)
10655 found_base_field = TRUE;
10656 if (!mono_type_is_valid_enum_basetype (field->type))
10661 if (!found_base_field)
10664 if (mono_class_get_method_count (klass) > 0)
10671 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10673 return gklass->context.class_inst == mono_class_get_generic_container (gklass->container_class)->context.class_inst;
10677 * mono_class_setup_interface_id:
10679 * Initializes MonoClass::interface_id if required.
10681 * LOCKING: Acquires the loader lock.
10684 mono_class_setup_interface_id (MonoClass *klass)
10686 mono_loader_lock ();
10687 if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10688 klass->interface_id = mono_get_unique_iid (klass);
10689 mono_loader_unlock ();
10693 * mono_class_alloc_ext:
10695 * Allocate klass->ext if not already done.
10698 mono_class_alloc_ext (MonoClass *klass)
10702 if (mono_class_get_ext (klass))
10705 ext = (MonoClassExt *)mono_class_alloc0 (klass, sizeof (MonoClassExt));
10706 mono_image_lock (klass->image);
10707 mono_memory_barrier ();
10708 if (!mono_class_get_ext (klass))
10709 mono_class_set_ext (klass, ext);
10710 class_ext_size += sizeof (MonoClassExt);
10712 mono_image_unlock (klass->image);
10716 * mono_class_setup_interfaces:
10718 * Initialize klass->interfaces/interfaces_count.
10719 * LOCKING: Acquires the loader lock.
10720 * This function can fail the type.
10723 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10725 int i, interface_count;
10726 MonoClass **interfaces;
10728 mono_error_init (error);
10730 if (klass->interfaces_inited)
10733 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10734 MonoType *args [1];
10736 /* generic IList, ICollection, IEnumerable */
10737 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10738 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10740 args [0] = &klass->element_class->byval_arg;
10741 interfaces [0] = mono_class_bind_generic_parameters (
10742 mono_defaults.generic_ilist_class, 1, args, FALSE);
10743 if (interface_count > 1)
10744 interfaces [1] = mono_class_bind_generic_parameters (
10745 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10746 } else if (mono_class_is_ginst (klass)) {
10747 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
10749 mono_class_setup_interfaces (gklass, error);
10750 if (!mono_error_ok (error)) {
10751 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10755 interface_count = gklass->interface_count;
10756 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10757 for (i = 0; i < interface_count; i++) {
10758 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (mono_class_get_generic_class (klass)), error);
10759 if (!mono_error_ok (error)) {
10760 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10765 interface_count = 0;
10769 mono_image_lock (klass->image);
10771 if (!klass->interfaces_inited) {
10772 klass->interface_count = interface_count;
10773 klass->interfaces = interfaces;
10775 mono_memory_barrier ();
10777 klass->interfaces_inited = TRUE;
10780 mono_image_unlock (klass->image);
10784 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10786 MonoClass *klass = field->parent;
10787 MonoImage *image = klass->image;
10788 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10790 int field_idx = field - klass->fields;
10792 mono_error_init (error);
10795 MonoClassField *gfield = >d->fields [field_idx];
10796 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10797 if (!mono_error_ok (error)) {
10798 char *full_name = mono_type_get_full_name (gtd);
10799 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));
10800 g_free (full_name);
10803 ftype = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10804 if (!mono_error_ok (error)) {
10805 char *full_name = mono_type_get_full_name (klass);
10806 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));
10807 g_free (full_name);
10811 guint32 cols [MONO_FIELD_SIZE];
10812 MonoGenericContainer *container = NULL;
10813 int idx = mono_class_get_first_field_idx (klass) + field_idx;
10815 /*FIXME, in theory we do not lazy load SRE fields*/
10816 g_assert (!image_is_dynamic (image));
10818 if (mono_class_is_gtd (klass)) {
10819 container = mono_class_get_generic_container (klass);
10821 container = mono_class_get_generic_container (gtd);
10822 g_assert (container);
10825 /* first_field_idx and idx points into the fieldptr table */
10826 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10828 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10829 char *full_name = mono_type_get_full_name (klass);
10830 mono_error_set_type_load_class (error, klass, "Could not verify field '%s:%s' signature", full_name, field->name);;
10831 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
10832 g_free (full_name);
10836 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10838 mono_metadata_decode_value (sig, &sig);
10839 /* FIELD signature == 0x06 */
10840 g_assert (*sig == 0x06);
10842 ftype = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10844 char *full_name = mono_type_get_full_name (klass);
10845 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));
10846 g_free (full_name);
10849 mono_memory_barrier ();
10850 field->type = ftype;
10854 mono_field_resolve_flags (MonoClassField *field)
10856 MonoClass *klass = field->parent;
10857 MonoImage *image = klass->image;
10858 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10859 int field_idx = field - klass->fields;
10863 MonoClassField *gfield = >d->fields [field_idx];
10864 return mono_field_get_flags (gfield);
10866 int idx = mono_class_get_first_field_idx (klass) + field_idx;
10868 /*FIXME, in theory we do not lazy load SRE fields*/
10869 g_assert (!image_is_dynamic (image));
10871 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10876 * mono_class_get_fields_lazy:
10877 * @klass: the MonoClass to act on
10879 * This routine is an iterator routine for retrieving the fields in a class.
10880 * Only minimal information about fields are loaded. Accessors must be used
10881 * for all MonoClassField returned.
10883 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10884 * iterate over all of the elements. When no more values are
10885 * available, the return value is NULL.
10887 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10890 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10892 MonoClassField* field;
10896 mono_class_setup_basic_field_info (klass);
10897 if (!klass->fields)
10899 /* start from the first */
10900 if (mono_class_get_field_count (klass)) {
10901 *iter = &klass->fields [0];
10902 return (MonoClassField *)*iter;
10908 field = (MonoClassField *)*iter;
10910 if (field < &klass->fields [mono_class_get_field_count (klass)]) {
10912 return (MonoClassField *)*iter;
10918 mono_class_full_name (MonoClass *klass)
10920 return mono_type_full_name (&klass->byval_arg);
10923 /* Declare all shared lazy type lookup functions */
10924 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, System.Runtime.InteropServices, SafeHandle)