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;
6014 mono_loader_unlock ();
6016 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6021 mono_class_setup_mono_type (klass);
6022 mono_loader_unlock ();
6023 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
6027 /** Is klass a Nullable<T> ginst? */
6029 mono_class_is_nullable (MonoClass *klass)
6031 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
6032 return gklass && gklass->container_class == mono_defaults.generic_nullable_class;
6036 /** if klass is T? return T */
6038 mono_class_get_nullable_param (MonoClass *klass)
6040 g_assert (mono_class_is_nullable (klass));
6041 return mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
6045 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
6049 MonoGenericClass *gclass = mono_class_get_generic_class (klass);
6051 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
6052 if (!mono_error_ok (&error)) {
6053 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
6054 klass->parent = mono_defaults.object_class;
6055 mono_class_set_type_load_failure (klass, "Parent is a generic type instantiation that failed due to: %s", mono_error_get_message (&error));
6056 mono_error_cleanup (&error);
6060 mono_class_setup_parent (klass, klass->parent);
6062 if (klass->enumtype) {
6063 klass->cast_class = gtd->cast_class;
6064 klass->element_class = gtd->element_class;
6069 mono_type_is_primitive (MonoType *type)
6071 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
6072 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
6076 * Create the `MonoClass' for an instantiation of a generic type.
6077 * We only do this if we actually need it.
6080 mono_generic_class_get_class (MonoGenericClass *gclass)
6082 MonoClass *klass, *gklass;
6084 if (gclass->cached_class)
6085 return gclass->cached_class;
6087 klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClassGenericInst));
6089 gklass = gclass->container_class;
6091 if (gklass->nested_in) {
6092 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
6093 klass->nested_in = gklass->nested_in;
6096 klass->name = gklass->name;
6097 klass->name_space = gklass->name_space;
6099 klass->image = gklass->image;
6100 klass->type_token = gklass->type_token;
6102 klass->class_kind = MONO_CLASS_GINST;
6104 ((MonoClassGenericInst*)klass)->generic_class = gclass;
6106 klass->byval_arg.type = MONO_TYPE_GENERICINST;
6107 klass->this_arg.type = klass->byval_arg.type;
6108 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
6109 klass->this_arg.byref = TRUE;
6110 klass->enumtype = gklass->enumtype;
6111 klass->valuetype = gklass->valuetype;
6113 if (gklass->image->assembly_name && !strcmp (gklass->image->assembly_name, "System.Numerics.Vectors") && !strcmp (gklass->name_space, "System.Numerics") && !strcmp (gklass->name, "Vector`1")) {
6114 g_assert (gclass->context.class_inst);
6115 g_assert (gclass->context.class_inst->type_argc > 0);
6116 if (mono_type_is_primitive (gclass->context.class_inst->type_argv [0]))
6117 klass->simd_type = 1;
6120 klass->cast_class = klass->element_class = klass;
6122 if (gclass->is_dynamic) {
6124 * 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.
6125 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
6126 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
6128 if (!gklass->wastypebuilder)
6131 if (klass->enumtype) {
6133 * For enums, gklass->fields might not been set, but instance_size etc. is
6134 * already set in mono_reflection_create_internal_class (). For non-enums,
6135 * these will be computed normally in mono_class_layout_fields ().
6137 klass->instance_size = gklass->instance_size;
6138 klass->sizes.class_size = gklass->sizes.class_size;
6139 klass->size_inited = 1;
6143 mono_loader_lock ();
6145 if (gclass->cached_class) {
6146 mono_loader_unlock ();
6147 return gclass->cached_class;
6150 if (record_gclass_instantiation > 0)
6151 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
6153 if (mono_class_is_nullable (klass))
6154 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
6156 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6158 mono_generic_class_setup_parent (klass, gklass);
6160 if (gclass->is_dynamic)
6161 mono_class_setup_supertypes (klass);
6163 mono_memory_barrier ();
6164 gclass->cached_class = klass;
6166 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6168 ++class_ginst_count;
6169 inflated_classes_size += sizeof (MonoClassGenericInst);
6171 mono_loader_unlock ();
6177 get_image_for_container (MonoGenericContainer *container)
6180 if (container->is_anonymous) {
6181 result = container->owner.image;
6184 if (container->is_method) {
6185 MonoMethod *method = container->owner.method;
6186 g_assert_checked (method);
6187 klass = method->klass;
6189 klass = container->owner.klass;
6191 g_assert_checked (klass);
6192 result = klass->image;
6199 get_image_for_generic_param (MonoGenericParam *param)
6201 MonoGenericContainer *container = mono_generic_param_owner (param);
6202 g_assert_checked (container);
6203 return get_image_for_container (container);
6206 // Make a string in the designated image consisting of a single integer.
6207 #define INT_STRING_SIZE 16
6209 make_generic_name_string (MonoImage *image, int num)
6211 char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
6212 g_snprintf (name, INT_STRING_SIZE, "%d", num);
6216 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
6217 // pinfo is derived from param by the caller for us.
6219 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
6221 MonoClass *klass, **ptr;
6223 MonoGenericContainer *container = mono_generic_param_owner (param);
6224 g_assert_checked (container);
6226 MonoImage *image = get_image_for_container (container);
6227 gboolean is_mvar = container->is_method;
6228 gboolean is_anonymous = container->is_anonymous;
6230 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassGenericParam));
6231 klass->class_kind = MONO_CLASS_GPARAM;
6232 classes_size += sizeof (MonoClassGenericParam);
6233 ++class_gparam_count;
6236 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
6238 int n = mono_generic_param_num (param);
6239 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
6243 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , "" );
6244 } else if (is_mvar) {
6245 MonoMethod *omethod = container->owner.method;
6246 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
6248 MonoClass *oklass = container->owner.klass;
6249 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
6252 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6254 // Count non-NULL items in pinfo->constraints
6257 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6261 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6262 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
6264 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
6265 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
6267 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
6270 if (count - pos > 0) {
6271 klass->interface_count = count - pos;
6272 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
6273 klass->interfaces_inited = TRUE;
6274 for (i = pos; i < count; i++)
6275 CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
6278 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
6280 klass->inited = TRUE;
6281 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class , klass );
6282 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
6284 klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6285 klass->this_arg.type = klass->byval_arg.type;
6286 CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param , param );
6287 CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
6288 klass->this_arg.byref = TRUE;
6290 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6291 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6293 /*Init these fields to sane values*/
6294 klass->min_align = 1;
6296 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6297 * constrained to, the JIT depends on this.
6299 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6300 mono_memory_barrier ();
6301 klass->size_inited = 1;
6303 mono_class_setup_supertypes (klass);
6305 if (count - pos > 0) {
6306 mono_class_setup_vtable (klass->parent);
6307 if (mono_class_has_failure (klass->parent))
6308 mono_class_set_type_load_failure (klass, "Failed to setup parent interfaces");
6310 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6316 #define FAST_CACHE_SIZE 16
6319 * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6320 * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6321 * we cache the MonoClasses.
6322 * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6323 * LOCKING: Takes the image lock depending on @take_lock.
6326 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6328 int n = mono_generic_param_num (param);
6329 MonoImage *image = get_image_for_generic_param (param);
6330 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6331 MonoClass *klass = NULL;
6336 // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6337 // For high numbers or constraints we have to use pointer hashes.
6338 if (param->gshared_constraint) {
6339 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6342 mono_image_lock (image);
6343 klass = (MonoClass *)g_hash_table_lookup (ht, param);
6345 mono_image_unlock (image);
6350 if (n < FAST_CACHE_SIZE) {
6352 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6354 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6356 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6359 mono_image_lock (image);
6360 klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6362 mono_image_unlock (image);
6369 * LOCKING: Image lock (param->image) must be held
6372 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6374 int n = mono_generic_param_num (param);
6375 MonoImage *image = get_image_for_generic_param (param);
6376 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6380 if (param->gshared_constraint) {
6381 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6383 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6384 mono_memory_barrier ();
6386 image->mvar_cache_constrained = ht;
6388 image->var_cache_constrained = ht;
6390 g_hash_table_insert (ht, param, klass);
6391 } else if (n < FAST_CACHE_SIZE) {
6393 /* Requires locking to avoid droping an already published class */
6394 if (!image->mvar_cache_fast)
6395 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6396 image->mvar_cache_fast [n] = klass;
6398 if (!image->var_cache_fast)
6399 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6400 image->var_cache_fast [n] = klass;
6403 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6405 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6407 ht = g_hash_table_new (NULL, NULL);
6408 mono_memory_barrier ();
6410 image->mvar_cache_slow = ht;
6412 image->var_cache_slow = ht;
6415 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6420 * LOCKING: Acquires the image lock (@image).
6423 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6425 MonoImage *image = get_image_for_generic_param (param);
6426 MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6427 MonoClass *klass, *klass2;
6429 // If a klass already exists for this object and is cached, return it.
6430 if (pinfo) // Non-anonymous
6431 klass = pinfo->pklass;
6433 klass = get_anon_gparam_class (param, TRUE);
6438 // Create a new klass
6439 klass = make_generic_param_class (param, pinfo);
6441 // Now we need to cache the klass we created.
6442 // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6443 // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6444 // and allow our newly-created klass object to just leak.
6445 mono_memory_barrier ();
6447 mono_image_lock (image);
6449 // Here "klass2" refers to the klass potentially created by the other thread.
6450 if (pinfo) // Repeat check from above
6451 klass2 = pinfo->pklass;
6453 klass2 = get_anon_gparam_class (param, FALSE);
6460 pinfo->pklass = klass;
6462 set_anon_gparam_class (param, klass);
6464 mono_image_unlock (image);
6466 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6468 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED); // Alert profiler about botched class create
6470 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6476 * mono_class_from_generic_parameter:
6477 * @param: Parameter to find/construct a class for.
6478 * @arg2: Is ignored.
6479 * @arg3: Is ignored.
6482 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6484 return mono_class_from_generic_parameter_internal (param);
6488 mono_ptr_class_get (MonoType *type)
6491 MonoClass *el_class;
6495 el_class = mono_class_from_mono_type (type);
6496 image = el_class->image;
6498 mono_image_lock (image);
6499 if (image->ptr_cache) {
6500 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6501 mono_image_unlock (image);
6505 mono_image_unlock (image);
6507 result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassPointer));
6509 classes_size += sizeof (MonoClassPointer);
6510 ++class_pointer_count;
6512 result->parent = NULL; /* no parent for PTR types */
6513 result->name_space = el_class->name_space;
6514 name = g_strdup_printf ("%s*", el_class->name);
6515 result->name = mono_image_strdup (image, name);
6516 result->class_kind = MONO_CLASS_POINTER;
6519 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6521 result->image = el_class->image;
6522 result->inited = TRUE;
6523 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6524 result->cast_class = result->element_class = el_class;
6525 result->blittable = TRUE;
6527 result->byval_arg.type = MONO_TYPE_PTR;
6528 result->this_arg.type = result->byval_arg.type;
6529 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6530 result->this_arg.byref = TRUE;
6532 mono_class_setup_supertypes (result);
6534 mono_image_lock (image);
6535 if (image->ptr_cache) {
6537 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6538 mono_image_unlock (image);
6539 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6543 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6545 g_hash_table_insert (image->ptr_cache, el_class, result);
6546 mono_image_unlock (image);
6548 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6554 mono_fnptr_class_get (MonoMethodSignature *sig)
6556 MonoClass *result, *cached;
6557 static GHashTable *ptr_hash = NULL;
6559 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6561 mono_loader_lock ();
6563 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6564 cached = (MonoClass *)g_hash_table_lookup (ptr_hash, sig);
6565 mono_loader_unlock ();
6569 result = g_new0 (MonoClass, 1);
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 result->image = mono_defaults.corlib; /* need to fix... */
6577 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6578 result->cast_class = result->element_class = result;
6579 result->byval_arg.type = MONO_TYPE_FNPTR;
6580 result->this_arg.type = result->byval_arg.type;
6581 result->this_arg.data.method = result->byval_arg.data.method = sig;
6582 result->this_arg.byref = TRUE;
6583 result->blittable = TRUE;
6584 result->inited = TRUE;
6586 mono_class_setup_supertypes (result);
6588 mono_loader_lock ();
6590 cached = (MonoClass *)g_hash_table_lookup (ptr_hash, sig);
6593 mono_loader_unlock ();
6597 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6599 classes_size += sizeof (MonoClassPointer);
6600 ++class_pointer_count;
6602 g_hash_table_insert (ptr_hash, sig, result);
6604 mono_loader_unlock ();
6606 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6612 * mono_class_from_mono_type:
6613 * @type: describes the type to return
6615 * This returns a MonoClass for the specified MonoType, the value is never NULL.
6618 mono_class_from_mono_type (MonoType *type)
6620 switch (type->type) {
6621 case MONO_TYPE_OBJECT:
6622 return type->data.klass? type->data.klass: mono_defaults.object_class;
6623 case MONO_TYPE_VOID:
6624 return type->data.klass? type->data.klass: mono_defaults.void_class;
6625 case MONO_TYPE_BOOLEAN:
6626 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6627 case MONO_TYPE_CHAR:
6628 return type->data.klass? type->data.klass: mono_defaults.char_class;
6630 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6632 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6634 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6636 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6638 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6640 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6642 return type->data.klass? type->data.klass: mono_defaults.int_class;
6644 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6646 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6648 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6650 return type->data.klass? type->data.klass: mono_defaults.single_class;
6652 return type->data.klass? type->data.klass: mono_defaults.double_class;
6653 case MONO_TYPE_STRING:
6654 return type->data.klass? type->data.klass: mono_defaults.string_class;
6655 case MONO_TYPE_TYPEDBYREF:
6656 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6657 case MONO_TYPE_ARRAY:
6658 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6660 return mono_ptr_class_get (type->data.type);
6661 case MONO_TYPE_FNPTR:
6662 return mono_fnptr_class_get (type->data.method);
6663 case MONO_TYPE_SZARRAY:
6664 return mono_array_class_get (type->data.klass, 1);
6665 case MONO_TYPE_CLASS:
6666 case MONO_TYPE_VALUETYPE:
6667 return type->data.klass;
6668 case MONO_TYPE_GENERICINST:
6669 return mono_generic_class_get_class (type->data.generic_class);
6670 case MONO_TYPE_MVAR:
6672 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6674 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6675 g_assert_not_reached ();
6678 // Yes, this returns NULL, even if it is documented as not doing so, but there
6679 // is no way for the code to make it this far, due to the assert above.
6684 * mono_type_retrieve_from_typespec
6685 * @image: context where the image is created
6686 * @type_spec: typespec token
6687 * @context: the generic context used to evaluate generic instantiations in
6690 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6692 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6694 *did_inflate = FALSE;
6699 if (context && (context->class_inst || context->method_inst)) {
6700 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6702 if (!mono_error_ok (error)) {
6708 *did_inflate = TRUE;
6715 * mono_class_create_from_typespec
6716 * @image: context where the image is created
6717 * @type_spec: typespec token
6718 * @context: the generic context used to evaluate generic instantiations in
6721 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6724 gboolean inflated = FALSE;
6725 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6726 return_val_if_nok (error, NULL);
6727 ret = mono_class_from_mono_type (t);
6729 mono_metadata_free_type (t);
6734 * mono_bounded_array_class_get:
6735 * @element_class: element class
6736 * @rank: the dimension of the array class
6737 * @bounded: whenever the array has non-zero bounds
6739 * Returns: A class object describing the array with element type @element_type and
6743 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6746 MonoClass *klass, *cached, *k;
6747 MonoClass *parent = NULL;
6748 GSList *list, *rootlist = NULL;
6752 g_assert (rank <= 255);
6755 /* bounded only matters for one-dimensional arrays */
6758 image = eclass->image;
6762 if (rank == 1 && !bounded) {
6764 * This case is very frequent not just during compilation because of calls
6765 * from mono_class_from_mono_type (), mono_array_new (),
6766 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6768 mono_os_mutex_lock (&image->szarray_cache_lock);
6769 if (!image->szarray_cache)
6770 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6771 cached = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6772 mono_os_mutex_unlock (&image->szarray_cache_lock);
6774 mono_loader_lock ();
6775 if (!image->array_cache)
6776 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6777 rootlist = (GSList *)g_hash_table_lookup (image->array_cache, eclass);
6778 for (list = rootlist; list; list = list->next) {
6779 k = (MonoClass *)list->data;
6780 if ((k->rank == rank) && (k->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6785 mono_loader_unlock ();
6790 parent = mono_defaults.array_class;
6791 if (!parent->inited)
6792 mono_class_init (parent);
6794 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassArray));
6796 klass->image = image;
6797 klass->name_space = eclass->name_space;
6798 klass->class_kind = MONO_CLASS_ARRAY;
6800 nsize = strlen (eclass->name);
6801 name = (char *)g_malloc (nsize + 2 + rank + 1);
6802 memcpy (name, eclass->name, nsize);
6805 memset (name + nsize + 1, ',', rank - 1);
6807 name [nsize + rank] = '*';
6808 name [nsize + rank + bounded] = ']';
6809 name [nsize + rank + bounded + 1] = 0;
6810 klass->name = mono_image_strdup (image, name);
6813 klass->type_token = 0;
6814 klass->parent = parent;
6815 klass->instance_size = mono_class_instance_size (klass->parent);
6817 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6818 /*Arrays of those two types are invalid.*/
6819 MonoError prepared_error;
6820 mono_error_init (&prepared_error);
6821 mono_error_set_invalid_program (&prepared_error, "Arrays of void or System.TypedReference types are invalid.");
6822 mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6823 mono_error_cleanup (&prepared_error);
6824 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6825 guint32 ref_info_handle = mono_class_get_ref_info_handle (eclass);
6826 if (!ref_info_handle || eclass->wastypebuilder) {
6827 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6828 g_assert (ref_info_handle && !eclass->wastypebuilder);
6830 /* element_size -1 is ok as this is not an instantitable type*/
6831 klass->sizes.element_size = -1;
6833 klass->sizes.element_size = mono_class_array_element_size (eclass);
6835 mono_class_setup_supertypes (klass);
6837 if (mono_class_is_ginst (eclass))
6838 mono_class_init (eclass);
6839 if (!eclass->size_inited)
6840 mono_class_setup_fields (eclass);
6841 mono_class_set_type_load_failure_causedby_class (klass, eclass, "Could not load array element type");
6842 /*FIXME we fail the array type, but we have to let other fields be set.*/
6844 klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6848 if (eclass->enumtype)
6849 klass->cast_class = eclass->element_class;
6851 klass->cast_class = eclass;
6853 switch (klass->cast_class->byval_arg.type) {
6855 klass->cast_class = mono_defaults.byte_class;
6858 klass->cast_class = mono_defaults.int16_class;
6861 #if SIZEOF_VOID_P == 4
6865 klass->cast_class = mono_defaults.int32_class;
6868 #if SIZEOF_VOID_P == 8
6872 klass->cast_class = mono_defaults.int64_class;
6878 klass->element_class = eclass;
6880 if ((rank > 1) || bounded) {
6881 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6882 klass->byval_arg.type = MONO_TYPE_ARRAY;
6883 klass->byval_arg.data.array = at;
6884 at->eklass = eclass;
6886 /* FIXME: complete.... */
6888 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6889 klass->byval_arg.data.klass = eclass;
6891 klass->this_arg = klass->byval_arg;
6892 klass->this_arg.byref = 1;
6894 mono_loader_lock ();
6896 /* Check cache again */
6898 if (rank == 1 && !bounded) {
6899 mono_os_mutex_lock (&image->szarray_cache_lock);
6900 cached = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6901 mono_os_mutex_unlock (&image->szarray_cache_lock);
6903 rootlist = (GSList *)g_hash_table_lookup (image->array_cache, eclass);
6904 for (list = rootlist; list; list = list->next) {
6905 k = (MonoClass *)list->data;
6906 if ((k->rank == rank) && (k->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6913 mono_loader_unlock ();
6917 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6919 classes_size += sizeof (MonoClassArray);
6920 ++class_array_count;
6922 if (rank == 1 && !bounded) {
6923 mono_os_mutex_lock (&image->szarray_cache_lock);
6924 g_hash_table_insert (image->szarray_cache, eclass, klass);
6925 mono_os_mutex_unlock (&image->szarray_cache_lock);
6927 list = g_slist_append (rootlist, klass);
6928 g_hash_table_insert (image->array_cache, eclass, list);
6931 mono_loader_unlock ();
6933 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6939 * mono_array_class_get:
6940 * @element_class: element class
6941 * @rank: the dimension of the array class
6943 * Returns: A class object describing the array with element type @element_type and
6947 mono_array_class_get (MonoClass *eclass, guint32 rank)
6949 return mono_bounded_array_class_get (eclass, rank, FALSE);
6953 * mono_class_instance_size:
6956 * Use to get the size of a class in bytes.
6958 * Returns: The size of an object instance
6961 mono_class_instance_size (MonoClass *klass)
6963 if (!klass->size_inited)
6964 mono_class_init (klass);
6966 return klass->instance_size;
6970 * mono_class_min_align:
6973 * Use to get the computed minimum alignment requirements for the specified class.
6975 * Returns: minimum alignment requirements
6978 mono_class_min_align (MonoClass *klass)
6980 if (!klass->size_inited)
6981 mono_class_init (klass);
6983 return klass->min_align;
6987 * mono_class_value_size:
6990 * This function is used for value types, and return the
6991 * space and the alignment to store that kind of value object.
6993 * Returns: the size of a value of kind @klass
6996 mono_class_value_size (MonoClass *klass, guint32 *align)
7000 /* fixme: check disable, because we still have external revereces to
7001 * mscorlib and Dummy Objects
7003 /*g_assert (klass->valuetype);*/
7005 size = mono_class_instance_size (klass) - sizeof (MonoObject);
7008 *align = klass->min_align;
7014 * mono_class_data_size:
7017 * Returns: The size of the static class data
7020 mono_class_data_size (MonoClass *klass)
7023 mono_class_init (klass);
7024 /* This can happen with dynamically created types */
7025 if (!klass->fields_inited)
7026 mono_class_setup_fields (klass);
7028 /* in arrays, sizes.class_size is unioned with element_size
7029 * and arrays have no static fields
7033 return klass->sizes.class_size;
7037 * Auxiliary routine to mono_class_get_field
7039 * Takes a field index instead of a field token.
7041 static MonoClassField *
7042 mono_class_get_field_idx (MonoClass *klass, int idx)
7044 mono_class_setup_fields (klass);
7045 if (mono_class_has_failure (klass))
7049 int first_field_idx = mono_class_get_first_field_idx (klass);
7050 int fcount = mono_class_get_field_count (klass);
7051 if (klass->image->uncompressed_metadata) {
7053 * first_field_idx points to the FieldPtr table, while idx points into the
7054 * Field table, so we have to do a search.
7056 /*FIXME this is broken for types with multiple fields with the same name.*/
7057 const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
7060 for (i = 0; i < fcount; ++i)
7061 if (mono_field_get_name (&klass->fields [i]) == name)
7062 return &klass->fields [i];
7063 g_assert_not_reached ();
7066 if ((idx >= first_field_idx) && (idx < first_field_idx + fcount)){
7067 return &klass->fields [idx - first_field_idx];
7071 klass = klass->parent;
7077 * mono_class_get_field:
7078 * @class: the class to lookup the field.
7079 * @field_token: the field token
7081 * Returns: A MonoClassField representing the type and offset of
7082 * the field, or a NULL value if the field does not belong to this
7086 mono_class_get_field (MonoClass *klass, guint32 field_token)
7088 int idx = mono_metadata_token_index (field_token);
7090 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
7092 return mono_class_get_field_idx (klass, idx - 1);
7096 * mono_class_get_field_from_name:
7097 * @klass: the class to lookup the field.
7098 * @name: the field name
7100 * Search the class @klass and it's parents for a field with the name @name.
7102 * Returns: The MonoClassField pointer of the named field or NULL
7105 mono_class_get_field_from_name (MonoClass *klass, const char *name)
7107 return mono_class_get_field_from_name_full (klass, name, NULL);
7111 * mono_class_get_field_from_name_full:
7112 * @klass: the class to lookup the field.
7113 * @name: the field name
7114 * @type: the type of the fields. This optional.
7116 * Search the class @klass and it's parents for a field with the name @name and type @type.
7118 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
7119 * of its generic type definition.
7121 * Returns: The MonoClassField pointer of the named field or NULL
7124 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
7128 mono_class_setup_fields (klass);
7129 if (mono_class_has_failure (klass))
7133 int fcount = mono_class_get_field_count (klass);
7134 for (i = 0; i < fcount; ++i) {
7135 MonoClassField *field = &klass->fields [i];
7137 if (strcmp (name, mono_field_get_name (field)) != 0)
7141 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
7142 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
7147 klass = klass->parent;
7153 * mono_class_get_field_token:
7154 * @field: the field we need the token of
7156 * Get the token of a field. Note that the tokesn is only valid for the image
7157 * the field was loaded from. Don't use this function for fields in dynamic types.
7159 * Returns: The token representing the field in the image it was loaded from.
7162 mono_class_get_field_token (MonoClassField *field)
7164 MonoClass *klass = field->parent;
7167 mono_class_setup_fields (klass);
7172 int first_field_idx = mono_class_get_first_field_idx (klass);
7173 int fcount = mono_class_get_field_count (klass);
7174 for (i = 0; i < fcount; ++i) {
7175 if (&klass->fields [i] == field) {
7176 int idx = first_field_idx + i + 1;
7178 if (klass->image->uncompressed_metadata)
7179 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
7180 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
7183 klass = klass->parent;
7186 g_assert_not_reached ();
7191 mono_field_get_index (MonoClassField *field)
7193 int index = field - field->parent->fields;
7194 g_assert (index >= 0 && index < mono_class_get_field_count (field->parent));
7200 * mono_class_get_field_default_value:
7202 * Return the default value of the field as a pointer into the metadata blob.
7205 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
7208 guint32 constant_cols [MONO_CONSTANT_SIZE];
7210 MonoClass *klass = field->parent;
7212 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7214 MonoClassExt *ext = mono_class_get_ext (klass);
7215 if (!ext || !ext->field_def_values) {
7216 MonoFieldDefaultValue *def_values;
7218 mono_class_alloc_ext (klass);
7219 ext = mono_class_get_ext (klass);
7221 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
7223 mono_image_lock (klass->image);
7224 mono_memory_barrier ();
7225 if (!ext->field_def_values)
7226 ext->field_def_values = def_values;
7227 mono_image_unlock (klass->image);
7230 field_index = mono_field_get_index (field);
7232 if (!ext->field_def_values [field_index].data) {
7233 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7237 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7239 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7240 ext->field_def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7241 ext->field_def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7244 *def_type = ext->field_def_values [field_index].def_type;
7245 return ext->field_def_values [field_index].data;
7249 mono_property_get_index (MonoProperty *prop)
7251 MonoClassExt *ext = mono_class_get_ext (prop->parent);
7252 int index = prop - ext->properties;
7254 g_assert (index >= 0 && index < ext->property.count);
7260 * mono_class_get_property_default_value:
7262 * Return the default value of the field as a pointer into the metadata blob.
7265 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7268 guint32 constant_cols [MONO_CONSTANT_SIZE];
7269 MonoClass *klass = property->parent;
7271 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7273 * We don't cache here because it is not used by C# so it's quite rare, but
7274 * we still do the lookup in klass->ext because that is where the data
7275 * is stored for dynamic assemblies.
7278 if (image_is_dynamic (klass->image)) {
7279 MonoClassExt *ext = mono_class_get_ext (klass);
7280 int prop_index = mono_property_get_index (property);
7281 if (ext->prop_def_values && ext->prop_def_values [prop_index].data) {
7282 *def_type = ext->prop_def_values [prop_index].def_type;
7283 return ext->prop_def_values [prop_index].data;
7287 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7291 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7292 *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7293 return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7297 mono_class_get_event_token (MonoEvent *event)
7299 MonoClass *klass = event->parent;
7303 MonoClassExt *ext = mono_class_get_ext (klass);
7305 for (i = 0; i < ext->event.count; ++i) {
7306 if (&ext->events [i] == event)
7307 return mono_metadata_make_token (MONO_TABLE_EVENT, ext->event.first + i + 1);
7310 klass = klass->parent;
7313 g_assert_not_reached ();
7318 * mono_class_get_property_from_name:
7320 * @name: name of the property to lookup in the specified class
7322 * Use this method to lookup a property in a class
7323 * Returns: the MonoProperty with the given name, or NULL if the property
7324 * does not exist on the @klass.
7327 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7331 gpointer iter = NULL;
7332 while ((p = mono_class_get_properties (klass, &iter))) {
7333 if (! strcmp (name, p->name))
7336 klass = klass->parent;
7342 * mono_class_get_property_token:
7343 * @prop: MonoProperty to query
7345 * Returns: The ECMA token for the specified property.
7348 mono_class_get_property_token (MonoProperty *prop)
7350 MonoClass *klass = prop->parent;
7354 gpointer iter = NULL;
7355 MonoClassExt *ext = mono_class_get_ext (klass);
7356 while ((p = mono_class_get_properties (klass, &iter))) {
7357 if (&ext->properties [i] == prop)
7358 return mono_metadata_make_token (MONO_TABLE_PROPERTY, ext->property.first + i + 1);
7362 klass = klass->parent;
7365 g_assert_not_reached ();
7370 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7372 const char *name, *nspace;
7373 if (image_is_dynamic (image))
7374 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7376 switch (type_token & 0xff000000){
7377 case MONO_TOKEN_TYPE_DEF: {
7378 guint32 cols [MONO_TYPEDEF_SIZE];
7379 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7380 guint tidx = mono_metadata_token_index (type_token);
7382 if (tidx > tt->rows)
7383 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7385 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7386 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7387 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7388 if (strlen (nspace) == 0)
7389 return g_strdup_printf ("%s", name);
7391 return g_strdup_printf ("%s.%s", nspace, name);
7394 case MONO_TOKEN_TYPE_REF: {
7396 guint32 cols [MONO_TYPEREF_SIZE];
7397 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7398 guint tidx = mono_metadata_token_index (type_token);
7401 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7403 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7404 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7405 mono_error_cleanup (&error);
7409 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7410 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7411 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7412 if (strlen (nspace) == 0)
7413 return g_strdup_printf ("%s", name);
7415 return g_strdup_printf ("%s.%s", nspace, name);
7418 case MONO_TOKEN_TYPE_SPEC:
7419 return g_strdup_printf ("Typespec 0x%08x", type_token);
7421 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7426 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7428 if (image_is_dynamic (image))
7429 return g_strdup_printf ("DynamicAssembly %s", image->name);
7431 switch (type_token & 0xff000000){
7432 case MONO_TOKEN_TYPE_DEF:
7433 if (image->assembly)
7434 return mono_stringify_assembly_name (&image->assembly->aname);
7435 else if (image->assembly_name)
7436 return g_strdup (image->assembly_name);
7437 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7438 case MONO_TOKEN_TYPE_REF: {
7440 MonoAssemblyName aname;
7441 guint32 cols [MONO_TYPEREF_SIZE];
7442 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7443 guint32 idx = mono_metadata_token_index (type_token);
7446 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7448 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7449 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7450 mono_error_cleanup (&error);
7453 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7455 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7456 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7457 case MONO_RESOLUTION_SCOPE_MODULE:
7459 return g_strdup ("");
7460 case MONO_RESOLUTION_SCOPE_MODULEREF:
7462 return g_strdup ("");
7463 case MONO_RESOLUTION_SCOPE_TYPEREF:
7465 return g_strdup ("");
7466 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7467 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7468 return mono_stringify_assembly_name (&aname);
7470 g_assert_not_reached ();
7474 case MONO_TOKEN_TYPE_SPEC:
7476 return g_strdup ("");
7478 g_assert_not_reached ();
7485 * mono_class_get_full:
7486 * @image: the image where the class resides
7487 * @type_token: the token for the class
7488 * @context: the generic context used to evaluate generic instantiations in
7489 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7491 * Returns: The MonoClass that represents @type_token in @image
7494 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7498 klass = mono_class_get_checked (image, type_token, &error);
7500 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7501 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7503 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7509 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7513 mono_error_init (error);
7514 klass = mono_class_get_checked (image, type_token, error);
7516 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7517 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7522 * mono_class_get_checked:
7523 * @image: the image where the class resides
7524 * @type_token: the token for the class
7525 * @error: error object to return any error
7527 * Returns: The MonoClass that represents @type_token in @image, or NULL on error.
7530 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7532 MonoClass *klass = NULL;
7534 mono_error_init (error);
7536 if (image_is_dynamic (image)) {
7537 int table = mono_metadata_token_table (type_token);
7539 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7540 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7543 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
7547 switch (type_token & 0xff000000){
7548 case MONO_TOKEN_TYPE_DEF:
7549 klass = mono_class_create_from_typedef (image, type_token, error);
7551 case MONO_TOKEN_TYPE_REF:
7552 klass = mono_class_from_typeref_checked (image, type_token, error);
7554 case MONO_TOKEN_TYPE_SPEC:
7555 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7558 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7562 /* Generic case, should be avoided for when a better error is possible. */
7563 if (!klass && mono_error_ok (error)) {
7564 char *name = mono_class_name_from_token (image, type_token);
7565 char *assembly = mono_assembly_name_from_token (image, type_token);
7566 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7574 * mono_type_get_checked:
7575 * @image: the image where the type resides
7576 * @type_token: the token for the type
7577 * @context: the generic context used to evaluate generic instantiations in
7578 * @error: Error handling context
7580 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7582 * Returns: The MonoType that represents @type_token in @image
7585 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7587 MonoType *type = NULL;
7588 gboolean inflated = FALSE;
7590 mono_error_init (error);
7592 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7593 if (image_is_dynamic (image)) {
7594 MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
7595 return_val_if_nok (error, NULL);
7596 return mono_class_get_type (klass);
7599 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7600 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7607 return mono_class_get_type (klass);
7610 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7617 MonoType *tmp = type;
7618 type = mono_class_get_type (mono_class_from_mono_type (type));
7619 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7620 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7621 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7623 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7625 if (type->type != tmp->type)
7628 mono_metadata_free_type (tmp);
7635 * @image: image where the class token will be looked up.
7636 * @type_token: a type token from the image
7638 * Returns the MonoClass with the given @type_token on the @image
7641 mono_class_get (MonoImage *image, guint32 type_token)
7643 return mono_class_get_full (image, type_token, NULL);
7647 * mono_image_init_name_cache:
7649 * Initializes the class name cache stored in image->name_cache.
7651 * LOCKING: Acquires the corresponding image lock.
7654 mono_image_init_name_cache (MonoImage *image)
7656 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7657 guint32 cols [MONO_TYPEDEF_SIZE];
7660 guint32 i, visib, nspace_index;
7661 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7663 if (image->name_cache)
7666 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7668 if (image_is_dynamic (image)) {
7669 mono_image_lock (image);
7670 if (image->name_cache) {
7671 /* Somebody initialized it before us */
7672 g_hash_table_destroy (the_name_cache);
7674 mono_atomic_store_release (&image->name_cache, the_name_cache);
7676 mono_image_unlock (image);
7680 /* Temporary hash table to avoid lookups in the nspace_table */
7681 name_cache2 = g_hash_table_new (NULL, NULL);
7683 for (i = 1; i <= t->rows; ++i) {
7684 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7685 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7687 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7688 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7690 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7692 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7693 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7695 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7696 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7697 if (!nspace_table) {
7698 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7699 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7700 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7703 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7706 /* Load type names from EXPORTEDTYPES table */
7708 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7709 guint32 cols [MONO_EXP_TYPE_SIZE];
7712 for (i = 0; i < t->rows; ++i) {
7713 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7715 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7716 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7720 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7721 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7723 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7724 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7725 if (!nspace_table) {
7726 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7727 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7728 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7731 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7735 g_hash_table_destroy (name_cache2);
7737 mono_image_lock (image);
7738 if (image->name_cache) {
7739 /* Somebody initialized it before us */
7740 g_hash_table_destroy (the_name_cache);
7742 mono_atomic_store_release (&image->name_cache, the_name_cache);
7744 mono_image_unlock (image);
7747 /*FIXME Only dynamic assemblies should allow this operation.*/
7749 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7750 const char *name, guint32 index)
7752 GHashTable *nspace_table;
7753 GHashTable *name_cache;
7756 mono_image_init_name_cache (image);
7757 mono_image_lock (image);
7759 name_cache = image->name_cache;
7760 if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7761 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7762 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7765 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7766 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7768 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7770 mono_image_unlock (image);
7779 find_nocase (gpointer key, gpointer value, gpointer user_data)
7781 char *name = (char*)key;
7782 FindUserData *data = (FindUserData*)user_data;
7784 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7785 data->value = value;
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.
7793 * @deprecated: use the mono_class_from_name_case_checked variant instead.
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.
7800 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7803 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7804 mono_error_cleanup (&error);
7810 * mono_class_from_name_case:
7811 * @image: The MonoImage where the type is looked up in
7812 * @name_space: the type namespace
7813 * @name: the type short name.
7816 * Obtains a MonoClass with a given namespace and a given name which
7817 * is located in the given MonoImage. The namespace and name
7818 * lookups are case insensitive.
7820 * Returns: The MonoClass if the given namespace and name were found, or NULL if it
7821 * was not found. The @error object will contain information about the problem
7825 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7827 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7828 guint32 cols [MONO_TYPEDEF_SIZE];
7833 mono_error_init (error);
7835 if (image_is_dynamic (image)) {
7837 FindUserData user_data;
7839 mono_image_init_name_cache (image);
7840 mono_image_lock (image);
7842 user_data.key = name_space;
7843 user_data.value = NULL;
7844 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7846 if (user_data.value) {
7847 GHashTable *nspace_table = (GHashTable*)user_data.value;
7849 user_data.key = name;
7850 user_data.value = NULL;
7852 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7854 if (user_data.value)
7855 token = GPOINTER_TO_UINT (user_data.value);
7858 mono_image_unlock (image);
7861 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7867 /* add a cache if needed */
7868 for (i = 1; i <= t->rows; ++i) {
7869 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7870 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7872 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7873 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7875 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7877 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7878 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7879 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7880 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7886 return_nested_in (MonoClass *klass, char *nested)
7889 char *s = strchr (nested, '/');
7890 gpointer iter = NULL;
7897 while ((found = mono_class_get_nested_types (klass, &iter))) {
7898 if (strcmp (found->name, nested) == 0) {
7900 return return_nested_in (found, s);
7908 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7910 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7911 MonoImage *file_image;
7915 mono_error_init (error);
7918 * The EXPORTEDTYPES table only contains public types, so have to search the
7920 * Note: image->modules contains the contents of the MODULEREF table, while
7921 * the real module list is in the FILE table.
7923 for (i = 0; i < file_table->rows; i++) {
7924 guint32 cols [MONO_FILE_SIZE];
7925 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7926 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7929 file_image = mono_image_load_file_for_image_checked (image, i + 1, error);
7931 klass = mono_class_from_name_checked (file_image, name_space, name, error);
7932 if (klass || !is_ok (error))
7941 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7943 GHashTable *nspace_table;
7944 MonoImage *loaded_image;
7951 mono_error_init (error);
7953 // Checking visited images avoids stack overflows when cyclic references exist.
7954 if (g_hash_table_lookup (visited_images, image))
7957 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7959 if ((nested = strchr (name, '/'))) {
7960 int pos = nested - name;
7961 int len = strlen (name);
7964 memcpy (buf, name, len + 1);
7966 nested = buf + pos + 1;
7970 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7971 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7972 gboolean res = get_class_from_name (image, name_space, name, &klass);
7975 klass = search_modules (image, name_space, name, error);
7980 return klass ? return_nested_in (klass, nested) : NULL;
7986 mono_image_init_name_cache (image);
7987 mono_image_lock (image);
7989 nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7992 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7994 mono_image_unlock (image);
7996 if (!token && image_is_dynamic (image) && image->modules) {
7997 /* Search modules as well */
7998 for (i = 0; i < image->module_count; ++i) {
7999 MonoImage *module = image->modules [i];
8001 klass = mono_class_from_name_checked (module, name_space, name, error);
8002 if (klass || !is_ok (error))
8008 klass = search_modules (image, name_space, name, error);
8009 if (klass || !is_ok (error))
8014 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
8015 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
8016 guint32 cols [MONO_EXP_TYPE_SIZE];
8019 idx = mono_metadata_token_index (token);
8021 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
8023 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
8024 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
8025 loaded_image = mono_assembly_load_module_checked (image->assembly, impl >> MONO_IMPLEMENTATION_BITS, error);
8028 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
8030 return klass ? return_nested_in (klass, nested) : NULL;
8032 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
8033 guint32 assembly_idx;
8035 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
8037 mono_assembly_load_reference (image, assembly_idx - 1);
8038 g_assert (image->references [assembly_idx - 1]);
8039 if (image->references [assembly_idx - 1] == (gpointer)-1)
8041 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
8043 return klass ? return_nested_in (klass, nested) : NULL;
8046 g_assert_not_reached ();
8050 token = MONO_TOKEN_TYPE_DEF | token;
8052 klass = mono_class_get_checked (image, token, error);
8054 return return_nested_in (klass, nested);
8059 * mono_class_from_name_checked:
8060 * @image: The MonoImage where the type is looked up in
8061 * @name_space: the type namespace
8062 * @name: the type short name.
8064 * Obtains a MonoClass with a given namespace and a given name which
8065 * is located in the given MonoImage.
8067 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
8068 * set if the class was not found or it will return NULL and set the error if there was a loading error.
8071 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
8074 GHashTable *visited_images;
8076 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
8078 klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
8080 g_hash_table_destroy (visited_images);
8086 * mono_class_from_name:
8087 * @image: The MonoImage where the type is looked up in
8088 * @name_space: the type namespace
8089 * @name: the type short name.
8091 * Obtains a MonoClass with a given namespace and a given name which
8092 * is located in the given MonoImage.
8094 * To reference nested classes, use the "/" character as a separator.
8095 * For example use "Foo/Bar" to reference the class Bar that is nested
8096 * inside Foo, like this: "class Foo { class Bar {} }".
8099 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
8104 klass = mono_class_from_name_checked (image, name_space, name, &error);
8105 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
8111 * mono_class_load_from_name:
8112 * @image: The MonoImage where the type is looked up in
8113 * @name_space: the type namespace
8114 * @name: the type short name.
8116 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
8117 * This function should be used by the runtime for critical types to which there's no way to recover but crash
8118 * If they are missing. Thing of System.Object or System.String.
8121 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
8126 klass = mono_class_from_name_checked (image, name_space, name, &error);
8128 g_error ("Runtime critical type %s.%s not found", name_space, name);
8129 if (!mono_error_ok (&error))
8130 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8135 * mono_class_try_load_from_name:
8136 * @image: The MonoImage where the type is looked up in
8137 * @name_space: the type namespace
8138 * @name: the type short name.
8140 * This function tries to load a type, returning the class was found or NULL otherwise.
8141 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
8143 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
8144 * a type that we would otherwise assume to be available but was not due some error.
8148 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
8153 klass = mono_class_from_name_checked (image, name_space, name, &error);
8154 if (!mono_error_ok (&error))
8155 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8161 * mono_class_is_subclass_of:
8162 * @klass: class to probe if it is a subclass of another one
8163 * @klassc: the class we suspect is the base class
8164 * @check_interfaces: whether we should perform interface checks
8166 * This method determines whether @klass is a subclass of @klassc.
8168 * If the @check_interfaces flag is set, then if @klassc is an interface
8169 * this method return TRUE if the @klass implements the interface or
8170 * if @klass is an interface, if one of its base classes is @klass.
8172 * If @check_interfaces is false then, then if @klass is not an interface
8173 * then it returns TRUE if the @klass is a subclass of @klassc.
8175 * if @klass is an interface and @klassc is System.Object, then this function
8180 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
8181 gboolean check_interfaces)
8183 /* FIXME test for interfaces with variant generic arguments */
8184 mono_class_init (klass);
8185 mono_class_init (klassc);
8187 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
8188 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
8190 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
8193 for (i = 0; i < klass->interface_count; i ++) {
8194 MonoClass *ic = klass->interfaces [i];
8199 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
8204 * MS.NET thinks interfaces are a subclass of Object, so we think it as
8207 if (klassc == mono_defaults.object_class)
8214 mono_type_is_generic_argument (MonoType *type)
8216 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
8220 mono_class_has_variant_generic_params (MonoClass *klass)
8223 MonoGenericContainer *container;
8225 if (!mono_class_is_ginst (klass))
8228 container = mono_class_get_generic_container (mono_class_get_generic_class (klass)->container_class);
8230 for (i = 0; i < container->type_argc; ++i)
8231 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8238 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8240 if (target == candidate)
8243 if (check_for_reference_conv &&
8244 mono_type_is_generic_argument (&target->byval_arg) &&
8245 mono_type_is_generic_argument (&candidate->byval_arg)) {
8246 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8247 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8249 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8252 if (!mono_class_is_assignable_from (target, candidate))
8258 * @container the generic container from the GTD
8259 * @klass: the class to be assigned to
8260 * @oklass: the source class
8262 * Both @klass and @oklass must be instances of the same generic interface.
8264 * Returns: TRUE if @klass can be assigned to a @klass variable
8267 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8270 MonoType **klass_argv, **oklass_argv;
8271 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8272 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8274 if (klass == oklass)
8277 /*Viable candidates are instances of the same generic interface*/
8278 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8281 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8282 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8284 for (j = 0; j < container->type_argc; ++j) {
8285 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8286 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8288 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8292 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8293 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8295 if (param1_class != param2_class) {
8296 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8297 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8299 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8300 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8310 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8312 MonoGenericParam *gparam, *ogparam;
8313 MonoGenericParamInfo *tinfo, *cinfo;
8314 MonoClass **candidate_class;
8315 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8318 if (target == candidate)
8320 if (target->byval_arg.type != candidate->byval_arg.type)
8323 gparam = target->byval_arg.data.generic_param;
8324 ogparam = candidate->byval_arg.data.generic_param;
8325 tinfo = mono_generic_param_info (gparam);
8326 cinfo = mono_generic_param_info (ogparam);
8328 class_constraint_satisfied = FALSE;
8329 valuetype_constraint_satisfied = FALSE;
8331 /*candidate must have a super set of target's special constraints*/
8332 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8333 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8335 if (cinfo->constraints) {
8336 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8337 MonoClass *cc = *candidate_class;
8339 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8340 class_constraint_satisfied = TRUE;
8341 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8342 valuetype_constraint_satisfied = TRUE;
8345 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8346 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8348 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8350 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8352 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8353 valuetype_constraint_satisfied)) {
8358 /*candidate type constraints must be a superset of target's*/
8359 if (tinfo->constraints) {
8360 MonoClass **target_class;
8361 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8362 MonoClass *tc = *target_class;
8365 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8366 * check it's constraints since it satisfy the constraint by itself.
8368 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8371 if (!cinfo->constraints)
8374 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8375 MonoClass *cc = *candidate_class;
8377 if (mono_class_is_assignable_from (tc, cc))
8381 * This happens when we have the following:
8383 * Bar<K> where K : IFace
8384 * Foo<T, U> where T : U where U : IFace
8386 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8389 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8390 if (mono_gparam_is_assignable_from (target, cc))
8394 if (!*candidate_class)
8399 /*candidate itself must have a constraint that satisfy target*/
8400 if (cinfo->constraints) {
8401 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8402 MonoClass *cc = *candidate_class;
8403 if (mono_class_is_assignable_from (target, cc))
8411 * mono_class_is_assignable_from:
8412 * @klass: the class to be assigned to
8413 * @oklass: the source class
8415 * Returns: TRUE if an instance of object oklass can be assigned to an
8416 * instance of object @klass
8419 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8422 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8424 mono_class_init (klass);
8426 if (!oklass->inited)
8427 mono_class_init (oklass);
8429 if (mono_class_has_failure (klass) || mono_class_has_failure (oklass))
8432 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8433 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8435 return mono_gparam_is_assignable_from (klass, oklass);
8438 if (MONO_CLASS_IS_INTERFACE (klass)) {
8439 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8440 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8441 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8445 for (i = 0; constraints [i]; ++i) {
8446 if (mono_class_is_assignable_from (klass, constraints [i]))
8454 /* interface_offsets might not be set for dynamic classes */
8455 if (mono_class_get_ref_info_handle (oklass) && !oklass->interface_bitmap) {
8457 * oklass might be a generic type parameter but they have
8458 * interface_offsets set.
8460 gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8461 if (!is_ok (&error)) {
8462 mono_error_cleanup (&error);
8467 if (!oklass->interface_bitmap)
8468 /* Happens with generic instances of not-yet created dynamic types */
8470 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8473 if (mono_class_has_variant_generic_params (klass)) {
8475 mono_class_setup_interfaces (oklass, &error);
8476 if (!mono_error_ok (&error)) {
8477 mono_error_cleanup (&error);
8481 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8482 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8483 MonoClass *iface = oklass->interfaces_packed [i];
8485 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8490 } else if (klass->delegate) {
8491 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8493 }else if (klass->rank) {
8494 MonoClass *eclass, *eoclass;
8496 if (oklass->rank != klass->rank)
8499 /* vectors vs. one dimensional arrays */
8500 if (oklass->byval_arg.type != klass->byval_arg.type)
8503 eclass = klass->cast_class;
8504 eoclass = oklass->cast_class;
8507 * a is b does not imply a[] is b[] when a is a valuetype, and
8508 * b is a reference type.
8511 if (eoclass->valuetype) {
8512 if ((eclass == mono_defaults.enum_class) ||
8513 (eclass == mono_defaults.enum_class->parent) ||
8514 (eclass == mono_defaults.object_class))
8518 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8519 } else if (mono_class_is_nullable (klass)) {
8520 if (mono_class_is_nullable (oklass))
8521 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8523 return mono_class_is_assignable_from (klass->cast_class, oklass);
8524 } else if (klass == mono_defaults.object_class)
8527 return mono_class_has_parent (oklass, klass);
8530 /*Check if @oklass is variant compatible with @klass.*/
8532 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8535 MonoType **klass_argv, **oklass_argv;
8536 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8537 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8539 /*Viable candidates are instances of the same generic interface*/
8540 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8543 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8544 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8546 for (j = 0; j < container->type_argc; ++j) {
8547 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8548 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8550 if (param1_class->valuetype != param2_class->valuetype)
8554 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8555 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8557 if (param1_class != param2_class) {
8558 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8559 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8561 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8562 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8570 /*Check if @candidate implements the interface @target*/
8572 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8576 gboolean is_variant = mono_class_has_variant_generic_params (target);
8578 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8579 if (mono_class_is_variant_compatible_slow (target, candidate))
8584 if (candidate == target)
8587 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8588 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8589 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (candidate);
8591 if (tb && tb->interfaces) {
8592 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8593 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8594 MonoClass *iface_class;
8596 /* we can't realize the type here since it can do pretty much anything. */
8599 iface_class = mono_class_from_mono_type (iface->type);
8600 if (iface_class == target)
8602 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8604 if (mono_class_implement_interface_slow (target, iface_class))
8609 /*setup_interfaces don't mono_class_init anything*/
8610 /*FIXME this doesn't handle primitive type arrays.
8611 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8612 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8614 mono_class_setup_interfaces (candidate, &error);
8615 if (!mono_error_ok (&error)) {
8616 mono_error_cleanup (&error);
8620 for (i = 0; i < candidate->interface_count; ++i) {
8621 if (candidate->interfaces [i] == target)
8624 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8627 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8631 candidate = candidate->parent;
8632 } while (candidate);
8638 * Check if @oklass can be assigned to @klass.
8639 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8642 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8644 if (candidate == target)
8646 if (target == mono_defaults.object_class)
8649 if (mono_class_has_parent (candidate, target))
8652 /*If target is not an interface there is no need to check them.*/
8653 if (MONO_CLASS_IS_INTERFACE (target))
8654 return mono_class_implement_interface_slow (target, candidate);
8656 if (target->delegate && mono_class_has_variant_generic_params (target))
8657 return mono_class_is_variant_compatible (target, candidate, FALSE);
8660 MonoClass *eclass, *eoclass;
8662 if (target->rank != candidate->rank)
8665 /* vectors vs. one dimensional arrays */
8666 if (target->byval_arg.type != candidate->byval_arg.type)
8669 eclass = target->cast_class;
8670 eoclass = candidate->cast_class;
8673 * a is b does not imply a[] is b[] when a is a valuetype, and
8674 * b is a reference type.
8677 if (eoclass->valuetype) {
8678 if ((eclass == mono_defaults.enum_class) ||
8679 (eclass == mono_defaults.enum_class->parent) ||
8680 (eclass == mono_defaults.object_class))
8684 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8686 /*FIXME properly handle nullables */
8687 /*FIXME properly handle (M)VAR */
8692 * mono_class_get_cctor:
8693 * @klass: A MonoClass pointer
8695 * Returns: The static constructor of @klass if it exists, NULL otherwise.
8698 mono_class_get_cctor (MonoClass *klass)
8700 MonoCachedClassInfo cached_info;
8702 if (image_is_dynamic (klass->image)) {
8704 * has_cctor is not set for these classes because mono_class_init () is
8707 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8710 if (!klass->has_cctor)
8713 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8715 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8716 if (!mono_error_ok (&error))
8717 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8721 if (mono_class_is_ginst (klass) && !klass->methods)
8722 return mono_class_get_inflated_method (klass, mono_class_get_cctor (mono_class_get_generic_class (klass)->container_class));
8724 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8728 * mono_class_get_finalizer:
8729 * @klass: The MonoClass pointer
8731 * Returns: The finalizer method of @klass if it exists, NULL otherwise.
8734 mono_class_get_finalizer (MonoClass *klass)
8736 MonoCachedClassInfo cached_info;
8739 mono_class_init (klass);
8740 if (!mono_class_has_finalizer (klass))
8743 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8745 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8746 if (!mono_error_ok (&error))
8747 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8750 mono_class_setup_vtable (klass);
8751 return klass->vtable [finalize_slot];
8756 * mono_class_needs_cctor_run:
8757 * @klass: the MonoClass pointer
8758 * @caller: a MonoMethod describing the caller
8760 * Determines whenever the class has a static constructor and whenever it
8761 * needs to be called when executing CALLER.
8764 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8768 method = mono_class_get_cctor (klass);
8770 return (method == caller) ? FALSE : TRUE;
8776 * mono_class_array_element_size:
8779 * Returns: The number of bytes an element of type @klass
8780 * uses when stored into an array.
8783 mono_class_array_element_size (MonoClass *klass)
8785 MonoType *type = &klass->byval_arg;
8788 switch (type->type) {
8791 case MONO_TYPE_BOOLEAN:
8795 case MONO_TYPE_CHAR:
8804 case MONO_TYPE_CLASS:
8805 case MONO_TYPE_STRING:
8806 case MONO_TYPE_OBJECT:
8807 case MONO_TYPE_SZARRAY:
8808 case MONO_TYPE_ARRAY:
8809 return sizeof (gpointer);
8814 case MONO_TYPE_VALUETYPE:
8815 if (type->data.klass->enumtype) {
8816 type = mono_class_enum_basetype (type->data.klass);
8817 klass = klass->element_class;
8820 return mono_class_instance_size (klass) - sizeof (MonoObject);
8821 case MONO_TYPE_GENERICINST:
8822 type = &type->data.generic_class->container_class->byval_arg;
8825 case MONO_TYPE_MVAR: {
8828 return mono_type_size (type, &align);
8830 case MONO_TYPE_VOID:
8834 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8840 * mono_array_element_size:
8841 * @ac: pointer to a #MonoArrayClass
8843 * Returns: The size of single array element.
8846 mono_array_element_size (MonoClass *ac)
8848 g_assert (ac->rank);
8849 return ac->sizes.element_size;
8853 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8854 MonoGenericContext *context)
8857 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8858 g_assert (mono_error_ok (&error));
8863 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8864 MonoGenericContext *context, MonoError *error)
8866 mono_error_init (error);
8868 if (image_is_dynamic (image)) {
8869 MonoClass *tmp_handle_class;
8870 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
8872 mono_error_assert_ok (error);
8873 g_assert (tmp_handle_class);
8875 *handle_class = tmp_handle_class;
8877 if (tmp_handle_class == mono_defaults.typehandle_class)
8878 return &((MonoClass*)obj)->byval_arg;
8883 switch (token & 0xff000000) {
8884 case MONO_TOKEN_TYPE_DEF:
8885 case MONO_TOKEN_TYPE_REF:
8886 case MONO_TOKEN_TYPE_SPEC: {
8889 *handle_class = mono_defaults.typehandle_class;
8890 type = mono_type_get_checked (image, token, context, error);
8894 mono_class_init (mono_class_from_mono_type (type));
8895 /* We return a MonoType* as handle */
8898 case MONO_TOKEN_FIELD_DEF: {
8900 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8902 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8906 *handle_class = mono_defaults.fieldhandle_class;
8907 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8911 mono_class_init (klass);
8912 return mono_class_get_field (klass, token);
8914 case MONO_TOKEN_METHOD_DEF:
8915 case MONO_TOKEN_METHOD_SPEC: {
8917 meth = mono_get_method_checked (image, token, NULL, context, error);
8919 *handle_class = mono_defaults.methodhandle_class;
8925 case MONO_TOKEN_MEMBER_REF: {
8926 guint32 cols [MONO_MEMBERREF_SIZE];
8928 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8929 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8930 mono_metadata_decode_blob_size (sig, &sig);
8931 if (*sig == 0x6) { /* it's a field */
8933 MonoClassField *field;
8934 field = mono_field_from_token_checked (image, token, &klass, context, error);
8936 *handle_class = mono_defaults.fieldhandle_class;
8940 meth = mono_get_method_checked (image, token, NULL, context, error);
8942 *handle_class = mono_defaults.methodhandle_class;
8947 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8953 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
8955 MonoClass *handle_class;
8956 mono_error_init (error);
8957 return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
8961 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
8963 return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
8966 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8969 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8971 get_cached_class_info = func;
8975 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8977 if (!get_cached_class_info)
8980 return get_cached_class_info (klass, res);
8984 mono_install_get_class_from_name (MonoGetClassFromName func)
8986 get_class_from_name = func;
8990 * mono_class_get_image:
8992 * Use this method to get the `MonoImage*` where this class came from.
8994 * Returns: The image where this class is defined.
8997 mono_class_get_image (MonoClass *klass)
8999 return klass->image;
9003 * mono_class_get_element_class:
9004 * @klass: the MonoClass to act on
9006 * Use this function to get the element class of an array.
9008 * Returns: The element class of an array.
9011 mono_class_get_element_class (MonoClass *klass)
9013 return klass->element_class;
9017 * mono_class_is_valuetype:
9018 * @klass: the MonoClass to act on
9020 * Use this method to determine if the provided `MonoClass*` represents a value type,
9021 * or a reference type.
9023 * Returns: TRUE if the MonoClass represents a ValueType, FALSE if it represents a reference type.
9026 mono_class_is_valuetype (MonoClass *klass)
9028 return klass->valuetype;
9032 * mono_class_is_enum:
9033 * @klass: the MonoClass to act on
9035 * Use this function to determine if the provided `MonoClass*` represents an enumeration.
9037 * Returns: TRUE if the MonoClass represents an enumeration.
9040 mono_class_is_enum (MonoClass *klass)
9042 return klass->enumtype;
9046 * mono_class_enum_basetype:
9047 * @klass: the MonoClass to act on
9049 * Use this function to get the underlying type for an enumeration value.
9051 * Returns: The underlying type representation for an enumeration.
9054 mono_class_enum_basetype (MonoClass *klass)
9056 if (klass->element_class == klass)
9057 /* SRE or broken types */
9060 return &klass->element_class->byval_arg;
9064 * mono_class_get_parent
9065 * @klass: the MonoClass to act on
9067 * Returns: The parent class for this class.
9070 mono_class_get_parent (MonoClass *klass)
9072 return klass->parent;
9076 * mono_class_get_nesting_type:
9077 * @klass: the MonoClass to act on
9079 * Use this function to obtain the class that the provided `MonoClass*` is nested on.
9081 * If the return is NULL, this indicates that this class is not nested.
9083 * Returns: The container type where this type is nested or NULL if this type is not a nested type.
9086 mono_class_get_nesting_type (MonoClass *klass)
9088 return klass->nested_in;
9092 * mono_class_get_rank:
9093 * @klass: the MonoClass to act on
9095 * Returns: The rank for the array (the number of dimensions).
9098 mono_class_get_rank (MonoClass *klass)
9104 * mono_class_get_name
9105 * @klass: the MonoClass to act on
9107 * Returns: The name of the class.
9110 mono_class_get_name (MonoClass *klass)
9116 * mono_class_get_namespace:
9117 * @klass: the MonoClass to act on
9119 * Returns: The namespace of the class.
9122 mono_class_get_namespace (MonoClass *klass)
9124 return klass->name_space;
9128 * mono_class_get_type:
9129 * @klass: the MonoClass to act on
9131 * This method returns the internal Type representation for the class.
9133 * Returns: The MonoType from the class.
9136 mono_class_get_type (MonoClass *klass)
9138 return &klass->byval_arg;
9142 * mono_class_get_type_token:
9143 * @klass: the MonoClass to act on
9145 * This method returns type token for the class.
9147 * Returns: The type token for the class.
9150 mono_class_get_type_token (MonoClass *klass)
9152 return klass->type_token;
9156 * mono_class_get_byref_type:
9157 * @klass: the MonoClass to act on
9162 mono_class_get_byref_type (MonoClass *klass)
9164 return &klass->this_arg;
9168 * mono_class_num_fields:
9169 * @klass: the MonoClass to act on
9171 * Returns: The number of static and instance fields in the class.
9174 mono_class_num_fields (MonoClass *klass)
9176 return mono_class_get_field_count (klass);
9180 * mono_class_num_methods:
9181 * @klass: the MonoClass to act on
9183 * Returns: The number of methods in the class.
9186 mono_class_num_methods (MonoClass *klass)
9188 return mono_class_get_method_count (klass);
9192 * mono_class_num_properties
9193 * @klass: the MonoClass to act on
9195 * Returns: The number of properties in the class.
9198 mono_class_num_properties (MonoClass *klass)
9200 mono_class_setup_properties (klass);
9202 return mono_class_get_ext (klass)->property.count;
9206 * mono_class_num_events:
9207 * @klass: the MonoClass to act on
9209 * Returns: The number of events in the class.
9212 mono_class_num_events (MonoClass *klass)
9214 mono_class_setup_events (klass);
9216 return mono_class_get_ext (klass)->event.count;
9220 * mono_class_get_fields:
9221 * @klass: the MonoClass to act on
9223 * This routine is an iterator routine for retrieving the fields in a class.
9225 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9226 * iterate over all of the elements. When no more values are
9227 * available, the return value is NULL.
9229 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
9232 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9234 MonoClassField* field;
9238 mono_class_setup_fields (klass);
9239 if (mono_class_has_failure (klass))
9241 /* start from the first */
9242 if (mono_class_get_field_count (klass)) {
9243 *iter = &klass->fields [0];
9244 return &klass->fields [0];
9250 field = (MonoClassField *)*iter;
9252 if (field < &klass->fields [mono_class_get_field_count (klass)]) {
9260 * mono_class_get_methods
9261 * @klass: the MonoClass to act on
9263 * This routine is an iterator routine for retrieving the fields in a class.
9265 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9266 * iterate over all of the elements. When no more values are
9267 * available, the return value is NULL.
9269 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
9272 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9274 MonoMethod** method;
9278 mono_class_setup_methods (klass);
9281 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9282 * FIXME we should better report this error to the caller
9284 if (!klass->methods)
9286 /* start from the first */
9287 if (mono_class_get_method_count (klass)) {
9288 *iter = &klass->methods [0];
9289 return klass->methods [0];
9295 method = (MonoMethod **)*iter;
9297 if (method < &klass->methods [mono_class_get_method_count (klass)]) {
9305 * mono_class_get_virtual_methods:
9307 * Iterate over the virtual methods of KLASS.
9309 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9312 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9314 MonoMethod** method;
9317 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9319 mono_class_setup_methods (klass);
9321 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9322 * FIXME we should better report this error to the caller
9324 if (!klass->methods)
9326 /* start from the first */
9327 method = &klass->methods [0];
9329 method = (MonoMethod **)*iter;
9332 int mcount = mono_class_get_method_count (klass);
9333 while (method < &klass->methods [mcount]) {
9334 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9338 if (method < &klass->methods [mcount]) {
9345 /* Search directly in metadata to avoid calling setup_methods () */
9346 MonoMethod *res = NULL;
9352 start_index = GPOINTER_TO_UINT (*iter);
9355 int first_idx = mono_class_get_first_method_idx (klass);
9356 int mcount = mono_class_get_method_count (klass);
9357 for (i = start_index; i < mcount; ++i) {
9360 /* first_idx points into the methodptr table */
9361 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
9363 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9369 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9370 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9372 /* Add 1 here so the if (*iter) check fails */
9373 *iter = GUINT_TO_POINTER (i + 1);
9382 * mono_class_get_properties:
9383 * @klass: the MonoClass to act on
9385 * This routine is an iterator routine for retrieving the properties in a class.
9387 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9388 * iterate over all of the elements. When no more values are
9389 * available, the return value is NULL.
9391 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9394 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9396 MonoProperty* property;
9400 mono_class_setup_properties (klass);
9401 MonoClassExt *ext = mono_class_get_ext (klass);
9402 /* start from the first */
9403 if (ext->property.count) {
9404 *iter = &ext->properties [0];
9405 return (MonoProperty *)*iter;
9411 property = (MonoProperty *)*iter;
9413 MonoClassExt *ext = mono_class_get_ext (klass);
9414 if (property < &ext->properties [ext->property.count]) {
9416 return (MonoProperty *)*iter;
9422 * mono_class_get_events:
9423 * @klass: the MonoClass to act on
9425 * This routine is an iterator routine for retrieving the properties in a class.
9427 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9428 * iterate over all of the elements. When no more values are
9429 * available, the return value is NULL.
9431 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9434 mono_class_get_events (MonoClass* klass, gpointer *iter)
9440 mono_class_setup_events (klass);
9441 MonoClassExt *ext = mono_class_get_ext (klass);
9442 /* start from the first */
9443 if (ext->event.count) {
9444 *iter = &ext->events [0];
9445 return (MonoEvent *)*iter;
9451 event = (MonoEvent *)*iter;
9453 MonoClassExt *ext = mono_class_get_ext (klass);
9454 if (event < &ext->events [ext->event.count]) {
9456 return (MonoEvent *)*iter;
9462 * mono_class_get_interfaces
9463 * @klass: the MonoClass to act on
9465 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9467 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9468 * iterate over all of the elements. When no more values are
9469 * available, the return value is NULL.
9471 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9474 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9482 mono_class_init (klass);
9483 if (!klass->interfaces_inited) {
9484 mono_class_setup_interfaces (klass, &error);
9485 if (!mono_error_ok (&error)) {
9486 mono_error_cleanup (&error);
9490 /* start from the first */
9491 if (klass->interface_count) {
9492 *iter = &klass->interfaces [0];
9493 return klass->interfaces [0];
9499 iface = (MonoClass **)*iter;
9501 if (iface < &klass->interfaces [klass->interface_count]) {
9509 setup_nested_types (MonoClass *klass)
9512 GList *classes, *nested_classes, *l;
9515 if (klass->nested_classes_inited)
9518 if (!klass->type_token)
9519 klass->nested_classes_inited = TRUE;
9521 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9525 guint32 cols [MONO_NESTED_CLASS_SIZE];
9526 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9527 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9528 if (!mono_error_ok (&error)) {
9529 /*FIXME don't swallow the error message*/
9530 mono_error_cleanup (&error);
9532 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9536 classes = g_list_prepend (classes, nclass);
9538 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9541 mono_class_alloc_ext (klass);
9543 nested_classes = NULL;
9544 for (l = classes; l; l = l->next)
9545 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9546 g_list_free (classes);
9548 mono_image_lock (klass->image);
9550 mono_memory_barrier ();
9551 if (!klass->nested_classes_inited) {
9552 mono_class_get_ext (klass)->nested_classes = nested_classes;
9553 mono_memory_barrier ();
9554 klass->nested_classes_inited = TRUE;
9557 mono_image_unlock (klass->image);
9561 * mono_class_get_nested_types
9562 * @klass: the MonoClass to act on
9564 * This routine is an iterator routine for retrieving the nested types of a class.
9565 * This works only if @klass is non-generic, or a generic type definition.
9567 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9568 * iterate over all of the elements. When no more values are
9569 * available, the return value is NULL.
9571 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9574 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9580 if (!klass->nested_classes_inited)
9581 setup_nested_types (klass);
9584 MonoClassExt *ext = mono_class_get_ext (klass);
9585 /* start from the first */
9586 if (ext && ext->nested_classes) {
9587 *iter = ext->nested_classes;
9588 return (MonoClass *)ext->nested_classes->data;
9590 /* no nested types */
9594 item = (GList *)*iter;
9598 return (MonoClass *)item->data;
9605 * mono_class_is_delegate
9606 * @klass: the MonoClass to act on
9608 * Returns: TRUE if the MonoClass represents a System.Delegate.
9611 mono_class_is_delegate (MonoClass *klass)
9613 return klass->delegate;
9617 * mono_class_implements_interface
9618 * @klass: The MonoClass to act on
9619 * @interface: The interface to check if @klass implements.
9621 * Returns: TRUE if @klass implements @interface.
9624 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9626 return mono_class_is_assignable_from (iface, klass);
9630 * mono_field_get_name:
9631 * @field: the MonoClassField to act on
9633 * Returns: The name of the field.
9636 mono_field_get_name (MonoClassField *field)
9642 * mono_field_get_type:
9643 * @field: the MonoClassField to act on
9645 * Returns: MonoType of the field.
9648 mono_field_get_type (MonoClassField *field)
9651 MonoType *type = mono_field_get_type_checked (field, &error);
9652 if (!mono_error_ok (&error)) {
9653 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9654 mono_error_cleanup (&error);
9661 * mono_field_get_type_checked:
9662 * @field: the MonoClassField to act on
9663 * @error: used to return any erro found while retrieving @field type
9665 * Returns: MonoType of the field.
9668 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9670 mono_error_init (error);
9672 mono_field_resolve_type (field, error);
9677 * mono_field_get_parent:
9678 * @field: the MonoClassField to act on
9680 * Returns: MonoClass where the field was defined.
9683 mono_field_get_parent (MonoClassField *field)
9685 return field->parent;
9689 * mono_field_get_flags;
9690 * @field: the MonoClassField to act on
9692 * The metadata flags for a field are encoded using the
9693 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9695 * Returns: The flags for the field.
9698 mono_field_get_flags (MonoClassField *field)
9701 return mono_field_resolve_flags (field);
9702 return field->type->attrs;
9706 * mono_field_get_offset:
9707 * @field: the MonoClassField to act on
9709 * Returns: The field offset.
9712 mono_field_get_offset (MonoClassField *field)
9714 return field->offset;
9718 mono_field_get_rva (MonoClassField *field)
9722 MonoClass *klass = field->parent;
9723 MonoFieldDefaultValue *field_def_values;
9725 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9727 MonoClassExt *ext = mono_class_get_ext (klass);
9728 if (!ext || !ext->field_def_values) {
9729 mono_class_alloc_ext (klass);
9730 ext = mono_class_get_ext (klass);
9732 field_def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
9734 mono_image_lock (klass->image);
9735 if (!ext->field_def_values)
9736 ext->field_def_values = field_def_values;
9737 mono_image_unlock (klass->image);
9740 field_index = mono_field_get_index (field);
9742 if (!ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9743 int first_field_idx = mono_class_get_first_field_idx (klass);
9744 mono_metadata_field_info (field->parent->image, first_field_idx + field_index, NULL, &rva, NULL);
9746 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9747 ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9750 return ext->field_def_values [field_index].data;
9754 * mono_field_get_data:
9755 * @field: the MonoClassField to act on
9757 * Returns: A pointer to the metadata constant value or to the field
9758 * data if it has an RVA flag.
9761 mono_field_get_data (MonoClassField *field)
9763 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9764 MonoTypeEnum def_type;
9766 return mono_class_get_field_default_value (field, &def_type);
9767 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9768 return mono_field_get_rva (field);
9775 * mono_property_get_name:
9776 * @prop: the MonoProperty to act on
9778 * Returns: The name of the property
9781 mono_property_get_name (MonoProperty *prop)
9787 * mono_property_get_set_method
9788 * @prop: the MonoProperty to act on.
9790 * Returns: The setter method of the property (A MonoMethod)
9793 mono_property_get_set_method (MonoProperty *prop)
9799 * mono_property_get_get_method
9800 * @prop: the MonoProperty to act on.
9802 * Returns: The setter method of the property (A MonoMethod)
9805 mono_property_get_get_method (MonoProperty *prop)
9811 * mono_property_get_parent:
9812 * @prop: the MonoProperty to act on.
9814 * Returns: The MonoClass where the property was defined.
9817 mono_property_get_parent (MonoProperty *prop)
9819 return prop->parent;
9823 * mono_property_get_flags:
9824 * @prop: the MonoProperty to act on.
9826 * The metadata flags for a property are encoded using the
9827 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9829 * Returns: The flags for the property.
9832 mono_property_get_flags (MonoProperty *prop)
9838 * mono_event_get_name:
9839 * @event: the MonoEvent to act on
9841 * Returns: The name of the event.
9844 mono_event_get_name (MonoEvent *event)
9850 * mono_event_get_add_method:
9851 * @event: The MonoEvent to act on.
9853 * Returns: The @add' method for the event (a MonoMethod).
9856 mono_event_get_add_method (MonoEvent *event)
9862 * mono_event_get_remove_method:
9863 * @event: The MonoEvent to act on.
9865 * Returns: The @remove method for the event (a MonoMethod).
9868 mono_event_get_remove_method (MonoEvent *event)
9870 return event->remove;
9874 * mono_event_get_raise_method:
9875 * @event: The MonoEvent to act on.
9877 * Returns: The @raise method for the event (a MonoMethod).
9880 mono_event_get_raise_method (MonoEvent *event)
9882 return event->raise;
9886 * mono_event_get_parent:
9887 * @event: the MonoEvent to act on.
9889 * Returns: The MonoClass where the event is defined.
9892 mono_event_get_parent (MonoEvent *event)
9894 return event->parent;
9898 * mono_event_get_flags
9899 * @event: the MonoEvent to act on.
9901 * The metadata flags for an event are encoded using the
9902 * EVENT_* constants. See the tabledefs.h file for details.
9904 * Returns: The flags for the event.
9907 mono_event_get_flags (MonoEvent *event)
9909 return event->attrs;
9913 * mono_class_get_method_from_name:
9914 * @klass: where to look for the method
9915 * @name: name of the method
9916 * @param_count: number of parameters. -1 for any number.
9918 * Obtains a MonoMethod with a given name and number of parameters.
9919 * It only works if there are no multiple signatures for any given method name.
9922 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9924 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9928 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9930 MonoMethod *res = NULL;
9933 /* Search directly in the metadata to avoid calling setup_methods () */
9934 int first_idx = mono_class_get_first_method_idx (klass);
9935 int mcount = mono_class_get_method_count (klass);
9936 for (i = 0; i < mcount; ++i) {
9938 guint32 cols [MONO_METHOD_SIZE];
9940 MonoMethodSignature *sig;
9942 /* first_idx points into the methodptr table */
9943 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, first_idx + i, cols, MONO_METHOD_SIZE);
9945 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9946 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9948 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9951 if (param_count == -1) {
9955 sig = mono_method_signature_checked (method, &error);
9957 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9960 if (sig->param_count == param_count) {
9971 * mono_class_get_method_from_name_flags:
9972 * @klass: where to look for the method
9973 * @name_space: name of the method
9974 * @param_count: number of parameters. -1 for any number.
9975 * @flags: flags which must be set in the method
9977 * Obtains a MonoMethod with a given name and number of parameters.
9978 * It only works if there are no multiple signatures for any given method name.
9981 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9983 MonoMethod *res = NULL;
9986 mono_class_init (klass);
9988 if (mono_class_is_ginst (klass) && !klass->methods) {
9989 res = mono_class_get_method_from_name_flags (mono_class_get_generic_class (klass)->container_class, name, param_count, flags);
9992 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9993 if (!mono_error_ok (&error))
9994 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9999 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
10000 mono_class_setup_methods (klass);
10002 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
10003 See mono/tests/array_load_exception.il
10004 FIXME we should better report this error to the caller
10006 if (!klass->methods)
10008 int mcount = mono_class_get_method_count (klass);
10009 for (i = 0; i < mcount; ++i) {
10010 MonoMethod *method = klass->methods [i];
10012 if (method->name[0] == name [0] &&
10013 !strcmp (name, method->name) &&
10014 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
10015 ((method->flags & flags) == flags)) {
10022 res = find_method_in_metadata (klass, name, param_count, flags);
10029 * mono_class_set_failure:
10030 * @klass: class in which the failure was detected
10031 * @ex_type: the kind of exception/error to be thrown (later)
10032 * @ex_data: exception data (specific to each type of exception/error)
10034 * Keep a detected failure informations in the class for later processing.
10035 * Note that only the first failure is kept.
10037 * LOCKING: Acquires the loader lock.
10040 mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error)
10042 g_assert (boxed_error != NULL);
10044 if (mono_class_has_failure (klass))
10047 mono_loader_lock ();
10048 klass->has_failure = 1;
10049 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, boxed_error);
10050 mono_loader_unlock ();
10056 mono_class_has_failure (const MonoClass *klass)
10058 g_assert (klass != NULL);
10059 return klass->has_failure != 0;
10064 * mono_class_set_type_load_failure:
10065 * @klass: class in which the failure was detected
10066 * @fmt: Printf-style error message string.
10068 * Collect detected failure informaion in the class for later processing.
10069 * The error is stored as a MonoErrorBoxed as with mono_error_set_type_load_class ()
10070 * Note that only the first failure is kept.
10072 * Returns FALSE if a failure was already set on the class, or TRUE otherwise.
10074 * LOCKING: Acquires the loader lock.
10077 mono_class_set_type_load_failure (MonoClass *klass, const char * fmt, ...)
10079 MonoError prepare_error;
10082 if (mono_class_has_failure (klass))
10085 mono_error_init (&prepare_error);
10087 va_start (args, fmt);
10088 mono_error_vset_type_load_class (&prepare_error, klass, fmt, args);
10091 MonoErrorBoxed *box = mono_error_box (&prepare_error, klass->image);
10092 mono_error_cleanup (&prepare_error);
10093 return mono_class_set_failure (klass, box);
10097 * mono_class_get_exception_data:
10099 * Return the exception_data property of KLASS.
10101 * LOCKING: Acquires the loader lock.
10104 mono_class_get_exception_data (const MonoClass *klass)
10106 return mono_image_property_lookup (klass->image, (MonoClass*)klass, MONO_CLASS_PROP_EXCEPTION_DATA);
10110 * mono_classes_init:
10112 * Initialize the resources used by this module.
10115 mono_classes_init (void)
10117 mono_os_mutex_init (&classes_mutex);
10119 mono_native_tls_alloc (&setup_fields_tls_id, NULL);
10120 mono_native_tls_alloc (&init_pending_tls_id, NULL);
10122 mono_counters_register ("MonoClassDef count",
10123 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_def_count);
10124 mono_counters_register ("MonoClassGtd count",
10125 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gtd_count);
10126 mono_counters_register ("MonoClassGenericInst count",
10127 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ginst_count);
10128 mono_counters_register ("MonoClassGenericParam count",
10129 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gparam_count);
10130 mono_counters_register ("MonoClassArray count",
10131 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_array_count);
10132 mono_counters_register ("MonoClassPointer count",
10133 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_pointer_count);
10134 mono_counters_register ("Inflated methods size",
10135 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
10136 mono_counters_register ("Inflated classes size",
10137 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
10138 mono_counters_register ("MonoClass size",
10139 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
10140 mono_counters_register ("MonoClassExt size",
10141 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
10143 mono_counters_register ("MonoClassExt count",
10144 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_count);
10148 * mono_classes_cleanup:
10150 * Free the resources used by this module.
10153 mono_classes_cleanup (void)
10155 mono_native_tls_free (setup_fields_tls_id);
10156 mono_native_tls_free (init_pending_tls_id);
10158 if (global_interface_bitset)
10159 mono_bitset_free (global_interface_bitset);
10160 global_interface_bitset = NULL;
10161 mono_os_mutex_destroy (&classes_mutex);
10165 * mono_class_get_exception_for_failure:
10166 * @klass: class in which the failure was detected
10168 * Return a constructed MonoException than the caller can then throw
10169 * using mono_raise_exception - or NULL if no failure is present (or
10170 * doesn't result in an exception).
10173 mono_class_get_exception_for_failure (MonoClass *klass)
10175 if (!mono_class_has_failure (klass))
10177 MonoError unboxed_error;
10178 mono_error_init (&unboxed_error);
10179 mono_error_set_for_class_failure (&unboxed_error, klass);
10180 return mono_error_convert_to_exception (&unboxed_error);
10184 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
10186 outer_klass = mono_class_get_generic_type_definition (outer_klass);
10187 inner_klass = mono_class_get_generic_type_definition (inner_klass);
10189 if (outer_klass == inner_klass)
10191 inner_klass = inner_klass->nested_in;
10192 } while (inner_klass);
10197 mono_class_get_generic_type_definition (MonoClass *klass)
10199 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
10200 return gklass ? gklass->container_class : klass;
10204 * Check if @klass is a subtype of @parent ignoring generic instantiations.
10206 * Generic instantiations are ignored for all super types of @klass.
10208 * Visibility checks ignoring generic instantiations.
10211 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
10214 klass = mono_class_get_generic_type_definition (klass);
10215 parent = mono_class_get_generic_type_definition (parent);
10216 mono_class_setup_supertypes (klass);
10218 for (i = 0; i < klass->idepth; ++i) {
10219 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
10225 * Subtype can only access parent members with family protection if the site object
10226 * is subclass of Subtype. For example:
10227 * class A { protected int x; }
10229 * void valid_access () {
10233 * void invalid_access () {
10240 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
10242 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
10245 if (context_klass == NULL)
10247 /*if access_klass is not member_klass context_klass must be type compat*/
10248 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10254 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10257 if (accessing == accessed)
10259 if (!accessed || !accessing)
10262 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10263 * anywhere so untrusted friends are not safe to access platform's code internals */
10264 if (mono_security_core_clr_enabled ()) {
10265 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10269 mono_assembly_load_friends (accessed);
10270 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10271 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10272 /* Be conservative with checks */
10273 if (!friend_->name)
10275 if (strcmp (accessing->aname.name, friend_->name))
10277 if (friend_->public_key_token [0]) {
10278 if (!accessing->aname.public_key_token [0])
10280 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10289 * If klass is a generic type or if it is derived from a generic type, return the
10290 * MonoClass of the generic definition
10291 * Returns NULL if not found
10294 get_generic_definition_class (MonoClass *klass)
10297 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
10298 if (gklass && gklass->container_class)
10299 return gklass->container_class;
10300 klass = klass->parent;
10306 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10309 for (i = 0; i < ginst->type_argc; ++i) {
10310 MonoType *type = ginst->type_argv[i];
10311 switch (type->type) {
10312 case MONO_TYPE_SZARRAY:
10313 if (!can_access_type (access_klass, type->data.klass))
10316 case MONO_TYPE_ARRAY:
10317 if (!can_access_type (access_klass, type->data.array->eklass))
10320 case MONO_TYPE_PTR:
10321 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10324 case MONO_TYPE_CLASS:
10325 case MONO_TYPE_VALUETYPE:
10326 case MONO_TYPE_GENERICINST:
10327 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10337 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10341 if (access_klass == member_klass)
10344 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10347 if (access_klass->element_class && !access_klass->enumtype)
10348 access_klass = access_klass->element_class;
10350 if (member_klass->element_class && !member_klass->enumtype)
10351 member_klass = member_klass->element_class;
10353 access_level = mono_class_get_flags (member_klass) & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10355 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10358 if (mono_class_is_ginst (member_klass) && !can_access_instantiation (access_klass, mono_class_get_generic_class (member_klass)->context.class_inst))
10361 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10364 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10367 /*Non nested type with nested visibility. We just fail it.*/
10368 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10371 switch (access_level) {
10372 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10373 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10375 case TYPE_ATTRIBUTE_PUBLIC:
10378 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10381 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10382 return is_nesting_type (member_klass, access_klass);
10384 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10385 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10387 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10388 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10390 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10391 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10392 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10394 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10395 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10396 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10401 /* FIXME: check visibility of type, too */
10403 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10405 MonoClass *member_generic_def;
10406 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10409 MonoGenericClass *access_gklass = mono_class_try_get_generic_class (access_klass);
10410 if (((access_gklass && access_gklass->container_class) ||
10411 mono_class_is_gtd (access_klass)) &&
10412 (member_generic_def = get_generic_definition_class (member_klass))) {
10413 MonoClass *access_container;
10415 if (mono_class_is_gtd (access_klass))
10416 access_container = access_klass;
10418 access_container = access_gklass->container_class;
10420 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10424 /* Partition I 8.5.3.2 */
10425 /* the access level values are the same for fields and methods */
10426 switch (access_level) {
10427 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10428 /* same compilation unit */
10429 return access_klass->image == member_klass->image;
10430 case FIELD_ATTRIBUTE_PRIVATE:
10431 return access_klass == member_klass;
10432 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10433 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10434 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10437 case FIELD_ATTRIBUTE_ASSEMBLY:
10438 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10439 case FIELD_ATTRIBUTE_FAMILY:
10440 if (is_valid_family_access (access_klass, member_klass, context_klass))
10443 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10444 if (is_valid_family_access (access_klass, member_klass, context_klass))
10446 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10447 case FIELD_ATTRIBUTE_PUBLIC:
10454 * mono_method_can_access_field:
10455 * @method: Method that will attempt to access the field
10456 * @field: the field to access
10458 * Used to determine if a method is allowed to access the specified field.
10460 * Returns: TRUE if the given @method is allowed to access the @field while following
10461 * the accessibility rules of the CLI.
10464 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10466 /* FIXME: check all overlapping fields */
10467 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10469 MonoClass *nested = method->klass->nested_in;
10471 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10474 nested = nested->nested_in;
10481 * mono_method_can_access_method:
10482 * @method: Method that will attempt to access the other method
10483 * @called: the method that we want to probe for accessibility.
10485 * Used to determine if the @method is allowed to access the specified @called method.
10487 * Returns: TRUE if the given @method is allowed to invoke the @called while following
10488 * the accessibility rules of the CLI.
10491 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10493 method = mono_method_get_method_definition (method);
10494 called = mono_method_get_method_definition (called);
10495 return mono_method_can_access_method_full (method, called, NULL);
10499 * mono_method_can_access_method_full:
10500 * @method: The caller method
10501 * @called: The called method
10502 * @context_klass: The static type on stack of the owner @called object used
10504 * This function must be used with instance calls, as they have more strict family accessibility.
10505 * It can be used with static methods, but context_klass should be NULL.
10507 * Returns: TRUE if caller have proper visibility and acessibility to @called
10510 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10512 /* Wrappers are except from access checks */
10513 if (method->wrapper_type != MONO_WRAPPER_NONE || called->wrapper_type != MONO_WRAPPER_NONE)
10516 MonoClass *access_class = method->klass;
10517 MonoClass *member_class = called->klass;
10518 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10520 MonoClass *nested = access_class->nested_in;
10522 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10525 nested = nested->nested_in;
10532 can = can_access_type (access_class, member_class);
10534 MonoClass *nested = access_class->nested_in;
10536 can = can_access_type (nested, member_class);
10539 nested = nested->nested_in;
10546 if (called->is_inflated) {
10547 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10548 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10557 * mono_method_can_access_field_full:
10558 * @method: The caller method
10559 * @field: The accessed field
10560 * @context_klass: The static type on stack of the owner @field object used
10562 * This function must be used with instance fields, as they have more strict family accessibility.
10563 * It can be used with static fields, but context_klass should be NULL.
10565 * Returns: TRUE if caller have proper visibility and acessibility to @field
10568 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10570 MonoClass *access_class = method->klass;
10571 MonoClass *member_class = field->parent;
10572 /* FIXME: check all overlapping fields */
10573 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10575 MonoClass *nested = access_class->nested_in;
10577 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10580 nested = nested->nested_in;
10587 can = can_access_type (access_class, member_class);
10589 MonoClass *nested = access_class->nested_in;
10591 can = can_access_type (nested, member_class);
10594 nested = nested->nested_in;
10604 * mono_class_can_access_class:
10605 * @source_class: The source class
10606 * @target_class: The accessed class
10608 * This function returns is @target_class is visible to @source_class
10610 * Returns: TRUE if source have proper visibility and acessibility to target
10613 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10615 return can_access_type (source_class, target_class);
10619 * mono_type_is_valid_enum_basetype:
10620 * @type: The MonoType to check
10622 * Returns: TRUE if the type can be used as the basetype of an enum
10624 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10625 switch (type->type) {
10628 case MONO_TYPE_BOOLEAN:
10631 case MONO_TYPE_CHAR:
10645 * mono_class_is_valid_enum:
10646 * @klass: An enum class to be validated
10648 * This method verify the required properties an enum should have.
10650 * Returns: TRUE if the informed enum class is valid
10652 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10653 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10654 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10657 mono_class_is_valid_enum (MonoClass *klass)
10659 MonoClassField * field;
10660 gpointer iter = NULL;
10661 gboolean found_base_field = FALSE;
10663 g_assert (klass->enumtype);
10664 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10665 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10669 if (!mono_class_is_auto_layout (klass))
10672 while ((field = mono_class_get_fields (klass, &iter))) {
10673 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10674 if (found_base_field)
10676 found_base_field = TRUE;
10677 if (!mono_type_is_valid_enum_basetype (field->type))
10682 if (!found_base_field)
10685 if (mono_class_get_method_count (klass) > 0)
10692 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10694 return gklass->context.class_inst == mono_class_get_generic_container (gklass->container_class)->context.class_inst;
10698 * mono_class_setup_interface_id:
10700 * Initializes MonoClass::interface_id if required.
10702 * LOCKING: Acquires the loader lock.
10705 mono_class_setup_interface_id (MonoClass *klass)
10707 mono_loader_lock ();
10708 if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10709 klass->interface_id = mono_get_unique_iid (klass);
10710 mono_loader_unlock ();
10714 * mono_class_alloc_ext:
10716 * Allocate klass->ext if not already done.
10719 mono_class_alloc_ext (MonoClass *klass)
10723 if (mono_class_get_ext (klass))
10726 ext = (MonoClassExt *)mono_class_alloc0 (klass, sizeof (MonoClassExt));
10727 mono_image_lock (klass->image);
10728 mono_memory_barrier ();
10729 if (!mono_class_get_ext (klass))
10730 mono_class_set_ext (klass, ext);
10731 class_ext_size += sizeof (MonoClassExt);
10733 mono_image_unlock (klass->image);
10737 * mono_class_setup_interfaces:
10739 * Initialize klass->interfaces/interfaces_count.
10740 * LOCKING: Acquires the loader lock.
10741 * This function can fail the type.
10744 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10746 int i, interface_count;
10747 MonoClass **interfaces;
10749 mono_error_init (error);
10751 if (klass->interfaces_inited)
10754 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10755 MonoType *args [1];
10757 /* generic IList, ICollection, IEnumerable */
10758 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10759 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10761 args [0] = &klass->element_class->byval_arg;
10762 interfaces [0] = mono_class_bind_generic_parameters (
10763 mono_defaults.generic_ilist_class, 1, args, FALSE);
10764 if (interface_count > 1)
10765 interfaces [1] = mono_class_bind_generic_parameters (
10766 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10767 } else if (mono_class_is_ginst (klass)) {
10768 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
10770 mono_class_setup_interfaces (gklass, error);
10771 if (!mono_error_ok (error)) {
10772 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10776 interface_count = gklass->interface_count;
10777 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10778 for (i = 0; i < interface_count; i++) {
10779 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (mono_class_get_generic_class (klass)), error);
10780 if (!mono_error_ok (error)) {
10781 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10786 interface_count = 0;
10790 mono_image_lock (klass->image);
10792 if (!klass->interfaces_inited) {
10793 klass->interface_count = interface_count;
10794 klass->interfaces = interfaces;
10796 mono_memory_barrier ();
10798 klass->interfaces_inited = TRUE;
10801 mono_image_unlock (klass->image);
10805 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10807 MonoClass *klass = field->parent;
10808 MonoImage *image = klass->image;
10809 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10811 int field_idx = field - klass->fields;
10813 mono_error_init (error);
10816 MonoClassField *gfield = >d->fields [field_idx];
10817 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10818 if (!mono_error_ok (error)) {
10819 char *full_name = mono_type_get_full_name (gtd);
10820 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));
10821 g_free (full_name);
10824 ftype = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10825 if (!mono_error_ok (error)) {
10826 char *full_name = mono_type_get_full_name (klass);
10827 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));
10828 g_free (full_name);
10832 guint32 cols [MONO_FIELD_SIZE];
10833 MonoGenericContainer *container = NULL;
10834 int idx = mono_class_get_first_field_idx (klass) + field_idx;
10836 /*FIXME, in theory we do not lazy load SRE fields*/
10837 g_assert (!image_is_dynamic (image));
10839 if (mono_class_is_gtd (klass)) {
10840 container = mono_class_get_generic_container (klass);
10842 container = mono_class_get_generic_container (gtd);
10843 g_assert (container);
10846 /* first_field_idx and idx points into the fieldptr table */
10847 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10849 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10850 char *full_name = mono_type_get_full_name (klass);
10851 mono_error_set_type_load_class (error, klass, "Could not verify field '%s:%s' signature", full_name, field->name);;
10852 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
10853 g_free (full_name);
10857 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10859 mono_metadata_decode_value (sig, &sig);
10860 /* FIELD signature == 0x06 */
10861 g_assert (*sig == 0x06);
10863 ftype = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10865 char *full_name = mono_type_get_full_name (klass);
10866 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));
10867 g_free (full_name);
10870 mono_memory_barrier ();
10871 field->type = ftype;
10875 mono_field_resolve_flags (MonoClassField *field)
10877 MonoClass *klass = field->parent;
10878 MonoImage *image = klass->image;
10879 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10880 int field_idx = field - klass->fields;
10884 MonoClassField *gfield = >d->fields [field_idx];
10885 return mono_field_get_flags (gfield);
10887 int idx = mono_class_get_first_field_idx (klass) + field_idx;
10889 /*FIXME, in theory we do not lazy load SRE fields*/
10890 g_assert (!image_is_dynamic (image));
10892 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10897 * mono_class_get_fields_lazy:
10898 * @klass: the MonoClass to act on
10900 * This routine is an iterator routine for retrieving the fields in a class.
10901 * Only minimal information about fields are loaded. Accessors must be used
10902 * for all MonoClassField returned.
10904 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10905 * iterate over all of the elements. When no more values are
10906 * available, the return value is NULL.
10908 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10911 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10913 MonoClassField* field;
10917 mono_class_setup_basic_field_info (klass);
10918 if (!klass->fields)
10920 /* start from the first */
10921 if (mono_class_get_field_count (klass)) {
10922 *iter = &klass->fields [0];
10923 return (MonoClassField *)*iter;
10929 field = (MonoClassField *)*iter;
10931 if (field < &klass->fields [mono_class_get_field_count (klass)]) {
10933 return (MonoClassField *)*iter;
10939 mono_class_full_name (MonoClass *klass)
10941 return mono_type_full_name (&klass->byval_arg);
10944 /* Declare all shared lazy type lookup functions */
10945 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, System.Runtime.InteropServices, SafeHandle)