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, 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 g_ptr_array_add (*res, ic);
2937 mono_class_init (ic);
2938 if (mono_class_has_failure (ic)) {
2939 mono_error_set_type_load_class (error, ic, "Error Loading class");
2943 collect_implemented_interfaces_aux (ic, res, error);
2944 return_if_nok (error);
2949 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2951 GPtrArray *res = NULL;
2953 collect_implemented_interfaces_aux (klass, &res, error);
2954 if (!mono_error_ok (error)) {
2956 g_ptr_array_free (res, TRUE);
2963 compare_interface_ids (const void *p_key, const void *p_element) {
2964 const MonoClass *key = (const MonoClass *)p_key;
2965 const MonoClass *element = *(const MonoClass **)p_element;
2967 return (key->interface_id - element->interface_id);
2970 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2972 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2973 MonoClass **result = (MonoClass **)mono_binary_search (
2975 klass->interfaces_packed,
2976 klass->interface_offsets_count,
2977 sizeof (MonoClass *),
2978 compare_interface_ids);
2980 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2987 * mono_class_interface_offset_with_variance:
2989 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2990 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2992 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2994 * FIXME figure out MS disambiguation rules and fix this function.
2997 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2998 int i = mono_class_interface_offset (klass, itf);
2999 *non_exact_match = FALSE;
3003 if (!mono_class_has_variant_generic_params (itf))
3006 for (i = 0; i < klass->interface_offsets_count; i++) {
3007 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
3008 *non_exact_match = TRUE;
3009 return klass->interface_offsets_packed [i];
3017 print_implemented_interfaces (MonoClass *klass) {
3020 GPtrArray *ifaces = NULL;
3022 int ancestor_level = 0;
3024 name = mono_type_get_full_name (klass);
3025 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
3028 for (i = 0; i < klass->interface_offsets_count; i++)
3029 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3030 klass->interfaces_packed [i]->interface_id,
3031 klass->interface_offsets_packed [i],
3032 mono_class_get_method_count (klass->interfaces_packed [i]),
3033 klass->interfaces_packed [i]->name_space,
3034 klass->interfaces_packed [i]->name );
3035 printf ("Interface flags: ");
3036 for (i = 0; i <= klass->max_interface_id; i++)
3037 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
3038 printf ("(%d,T)", i);
3040 printf ("(%d,F)", i);
3042 printf ("Dump interface flags:");
3043 #ifdef COMPRESSED_INTERFACE_BITMAP
3045 const uint8_t* p = klass->interface_bitmap;
3046 i = klass->max_interface_id;
3048 printf (" %d x 00 %02X", p [0], p [1]);
3054 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
3055 printf (" %02X", klass->interface_bitmap [i]);
3058 while (klass != NULL) {
3059 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
3060 ifaces = mono_class_get_implemented_interfaces (klass, &error);
3061 if (!mono_error_ok (&error)) {
3062 printf (" Type failed due to %s\n", mono_error_get_message (&error));
3063 mono_error_cleanup (&error);
3064 } else if (ifaces) {
3065 for (i = 0; i < ifaces->len; i++) {
3066 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3067 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
3068 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3070 mono_class_interface_offset (klass, ic),
3071 mono_class_get_method_count (ic),
3075 g_ptr_array_free (ifaces, TRUE);
3078 klass = klass->parent;
3083 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
3086 args [0] = &arg0->byval_arg;
3088 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
3092 array_class_get_if_rank (MonoClass *klass, guint rank)
3094 return rank ? mono_array_class_get (klass, rank) : klass;
3098 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
3100 valuetype_types [0] = eclass;
3101 if (eclass == mono_defaults.int16_class)
3102 valuetype_types [1] = mono_defaults.uint16_class;
3103 else if (eclass == mono_defaults.uint16_class)
3104 valuetype_types [1] = mono_defaults.int16_class;
3105 else if (eclass == mono_defaults.int32_class)
3106 valuetype_types [1] = mono_defaults.uint32_class;
3107 else if (eclass == mono_defaults.uint32_class)
3108 valuetype_types [1] = mono_defaults.int32_class;
3109 else if (eclass == mono_defaults.int64_class)
3110 valuetype_types [1] = mono_defaults.uint64_class;
3111 else if (eclass == mono_defaults.uint64_class)
3112 valuetype_types [1] = mono_defaults.int64_class;
3113 else if (eclass == mono_defaults.byte_class)
3114 valuetype_types [1] = mono_defaults.sbyte_class;
3115 else if (eclass == mono_defaults.sbyte_class)
3116 valuetype_types [1] = mono_defaults.byte_class;
3117 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
3118 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
3121 static GENERATE_GET_CLASS_WITH_CACHE (generic_icollection, System.Collections.Generic, ICollection`1)
3122 static GENERATE_GET_CLASS_WITH_CACHE (generic_ienumerable, System.Collections.Generic, IEnumerable`1)
3123 static GENERATE_GET_CLASS_WITH_CACHE (generic_ienumerator, System.Collections.Generic, IEnumerator`1)
3124 static GENERATE_GET_CLASS_WITH_CACHE (generic_ireadonlylist, System.Collections.Generic, IReadOnlyList`1)
3125 static GENERATE_GET_CLASS_WITH_CACHE (generic_ireadonlycollection, System.Collections.Generic, IReadOnlyCollection`1)
3127 /* this won't be needed once bug #325495 is completely fixed
3128 * though we'll need something similar to know which interfaces to allow
3129 * in arrays when they'll be lazyly created
3131 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
3132 * MS returns diferrent types based on which instance is called. For example:
3133 * object obj = new byte[10][];
3134 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
3135 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
3138 * Fixing this should kill quite some code, save some bits and improve compatibility.
3141 get_implicit_generic_array_interfaces (MonoClass *klass, int *num, int *is_enumerator)
3143 MonoClass *eclass = klass->element_class;
3144 MonoClass* generic_icollection_class;
3145 MonoClass* generic_ienumerable_class;
3146 MonoClass* generic_ienumerator_class;
3147 MonoClass* generic_ireadonlylist_class;
3148 MonoClass* generic_ireadonlycollection_class;
3149 MonoClass *valuetype_types[2] = { NULL, NULL };
3150 MonoClass **interfaces = NULL;
3151 int i, nifaces, interface_count, real_count, original_rank;
3153 gboolean internal_enumerator;
3154 gboolean eclass_is_valuetype;
3156 if (!mono_defaults.generic_ilist_class) {
3160 internal_enumerator = FALSE;
3161 eclass_is_valuetype = FALSE;
3162 original_rank = eclass->rank;
3163 if (klass->byval_arg.type != MONO_TYPE_SZARRAY) {
3164 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
3165 if (gklass && klass->nested_in == mono_defaults.array_class && strcmp (klass->name, "InternalEnumerator`1") == 0) {
3167 * For a Enumerator<T[]> we need to get the list of interfaces for T.
3169 eclass = mono_class_from_mono_type (gklass->context.class_inst->type_argv [0]);
3170 original_rank = eclass->rank;
3172 eclass = eclass->element_class;
3173 internal_enumerator = TRUE;
3174 *is_enumerator = TRUE;
3182 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
3183 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
3185 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
3187 generic_icollection_class = mono_class_get_generic_icollection_class ();
3188 generic_ienumerable_class = mono_class_get_generic_ienumerable_class ();
3189 generic_ienumerator_class = mono_class_get_generic_ienumerator_class ();
3190 generic_ireadonlylist_class = mono_class_get_generic_ireadonlylist_class ();
3191 generic_ireadonlycollection_class = mono_class_get_generic_ireadonlycollection_class ();
3193 mono_class_init (eclass);
3196 * Arrays in 2.0 need to implement a number of generic interfaces
3197 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
3198 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
3199 * We collect the types needed to build the
3200 * instantiations in interfaces at intervals of 3/5, because 3/5 are
3201 * the generic interfaces needed to implement.
3203 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
3204 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
3206 if (eclass->valuetype) {
3207 nifaces = generic_ireadonlylist_class ? 5 : 3;
3208 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
3210 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
3211 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
3212 if (internal_enumerator) {
3214 if (valuetype_types [1])
3218 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3219 interfaces [0] = valuetype_types [0];
3220 if (valuetype_types [1])
3221 interfaces [nifaces] = valuetype_types [1];
3223 eclass_is_valuetype = TRUE;
3226 int idepth = eclass->idepth;
3227 if (!internal_enumerator)
3229 nifaces = generic_ireadonlylist_class ? 2 : 3;
3231 // FIXME: This doesn't seem to work/required for generic params
3232 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
3233 mono_class_setup_interface_offsets (eclass);
3235 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
3236 /* we add object for interfaces and the supertypes for the other
3237 * types. The last of the supertypes is the element class itself which we
3238 * already created the explicit interfaces for (so we include it for IEnumerator
3239 * and exclude it for arrays).
3241 if (MONO_CLASS_IS_INTERFACE (eclass))
3244 interface_count += idepth;
3245 if (eclass->rank && eclass->element_class->valuetype) {
3246 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3247 if (valuetype_types [1])
3250 /* IList, ICollection, IEnumerable, IReadOnlyList */
3251 interface_count *= nifaces;
3252 real_count = interface_count;
3253 if (internal_enumerator) {
3254 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3255 if (valuetype_types [1])
3258 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3259 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3260 interfaces [0] = mono_defaults.object_class;
3264 for (i = 0; i < idepth; i++) {
3265 mono_class_init (eclass->supertypes [i]);
3266 interfaces [j] = eclass->supertypes [i];
3270 if (all_interfaces) {
3271 for (i = 0; i < eclass->interface_offsets_count; i++) {
3272 interfaces [j] = eclass->interfaces_packed [i];
3276 for (i = 0; i < eclass->interface_count; i++) {
3277 interfaces [j] = eclass->interfaces [i];
3281 if (valuetype_types [1]) {
3282 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3287 /* instantiate the generic interfaces */
3288 for (i = 0; i < interface_count; i += nifaces) {
3289 MonoClass *iface = interfaces [i];
3291 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3292 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3294 if (eclass->valuetype) {
3295 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3296 if (generic_ireadonlylist_class) {
3297 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3298 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3301 if (!generic_ireadonlylist_class)
3302 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3305 if (internal_enumerator) {
3307 /* instantiate IEnumerator<iface> */
3308 for (i = 0; i < interface_count; i++) {
3309 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3311 j = interface_count;
3312 if (!eclass_is_valuetype) {
3313 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3314 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3317 for (i = 0; i < eclass->idepth; i++) {
3318 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3322 for (i = 0; i < eclass->interface_offsets_count; i++) {
3323 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3327 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3329 if (valuetype_types [1])
3330 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3334 char *type_name = mono_type_get_name_full (&klass->byval_arg, 0);
3335 for (i = 0; i < real_count; ++i) {
3336 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3337 g_print ("%s implements %s\n", type_name, name);
3348 find_array_interface (MonoClass *klass, const char *name)
3351 for (i = 0; i < klass->interface_count; ++i) {
3352 if (strcmp (klass->interfaces [i]->name, name) == 0)
3359 * Return the number of virtual methods.
3360 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3361 * Return -1 on failure.
3362 * FIXME It would be nice if this information could be cached somewhere.
3365 count_virtual_methods (MonoClass *klass)
3367 int i, mcount, vcount = 0;
3369 klass = mono_class_get_generic_type_definition (klass); /*We can find this information by looking at the GTD*/
3371 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
3372 mono_class_setup_methods (klass);
3373 if (mono_class_has_failure (klass))
3376 mcount = mono_class_get_method_count (klass);
3377 for (i = 0; i < mcount; ++i) {
3378 flags = klass->methods [i]->flags;
3379 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3383 int first_idx = mono_class_get_first_method_idx (klass);
3384 mcount = mono_class_get_method_count (klass);
3385 for (i = 0; i < mcount; ++i) {
3386 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
3388 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3396 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3404 m = (l + num_ifaces) / 2;
3405 if (interfaces_full [m] == ic)
3407 if (l == num_ifaces)
3409 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3418 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3420 int i = find_interface (num_ifaces, interfaces_full, ic);
3422 return interface_offsets_full [i];
3427 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3429 int i = find_interface (num_ifaces, interfaces_full, ic);
3433 interface_offsets_full [i] = offset;
3436 for (i = 0; i < num_ifaces; ++i) {
3437 if (interfaces_full [i]) {
3439 if (interfaces_full [i]->interface_id < ic->interface_id)
3442 while (end < num_ifaces && interfaces_full [end]) end++;
3443 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3444 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3446 interfaces_full [i] = ic;
3447 interface_offsets_full [i] = offset;
3453 #ifdef COMPRESSED_INTERFACE_BITMAP
3456 * Compressed interface bitmap design.
3458 * Interface bitmaps take a large amount of memory, because their size is
3459 * linear with the maximum interface id assigned in the process (each interface
3460 * is assigned a unique id as it is loaded). The number of interface classes
3461 * is high because of the many implicit interfaces implemented by arrays (we'll
3462 * need to lazy-load them in the future).
3463 * Most classes implement a very small number of interfaces, so the bitmap is
3464 * sparse. This bitmap needs to be checked by interface casts, so access to the
3465 * needed bit must be fast and doable with few jit instructions.
3467 * The current compression format is as follows:
3468 * *) it is a sequence of one or more two-byte elements
3469 * *) the first byte in the element is the count of empty bitmap bytes
3470 * at the current bitmap position
3471 * *) the second byte in the element is an actual bitmap byte at the current
3474 * As an example, the following compressed bitmap bytes:
3475 * 0x07 0x01 0x00 0x7
3476 * correspond to the following bitmap:
3477 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3479 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3480 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3481 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3485 * mono_compress_bitmap:
3486 * @dest: destination buffer
3487 * @bitmap: bitmap buffer
3488 * @size: size of @bitmap in bytes
3490 * This is a mono internal function.
3491 * The @bitmap data is compressed into a format that is small but
3492 * still searchable in few instructions by the JIT and runtime.
3493 * The compressed data is stored in the buffer pointed to by the
3494 * @dest array. Passing a #NULL value for @dest allows to just compute
3495 * the size of the buffer.
3496 * This compression algorithm assumes the bits set in the bitmap are
3497 * few and far between, like in interface bitmaps.
3498 * Returns: The size of the compressed bitmap in bytes.
3501 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3505 const uint8_t *end = bitmap + size;
3506 while (bitmap < end) {
3507 if (*bitmap || numz == 255) {
3531 * mono_class_interface_match:
3532 * @bitmap: a compressed bitmap buffer
3533 * @id: the index to check in the bitmap
3535 * This is a mono internal function.
3536 * Checks if a bit is set in a compressed interface bitmap. @id must
3537 * be already checked for being smaller than the maximum id encoded in the
3540 * Returns: A non-zero value if bit @id is set in the bitmap @bitmap,
3544 mono_class_interface_match (const uint8_t *bitmap, int id)
3547 id -= bitmap [0] * 8;
3551 return bitmap [1] & (1 << id);
3560 * Return -1 on failure and set klass->has_failure and store a MonoErrorBoxed with the details.
3561 * LOCKING: Acquires the loader lock.
3564 setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite)
3568 int i, j, num_ifaces;
3570 MonoClass **interfaces_full = NULL;
3571 int *interface_offsets_full = NULL;
3573 GPtrArray **ifaces_array = NULL;
3574 int interface_offsets_count;
3575 MonoClass **array_interfaces = NULL;
3576 int num_array_interfaces;
3577 int is_enumerator = FALSE;
3579 mono_loader_lock ();
3581 mono_class_setup_supertypes (klass);
3583 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3584 * implicit interfaces have the property that they are assigned the same slot in the
3585 * vtables for compatible interfaces
3587 array_interfaces = get_implicit_generic_array_interfaces (klass, &num_array_interfaces, &is_enumerator);
3589 /* compute maximum number of slots and maximum interface id */
3591 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3592 ifaces_array = g_new0 (GPtrArray *, klass->idepth);
3593 for (j = 0; j < klass->idepth; j++) {
3594 k = klass->supertypes [j];
3596 num_ifaces += k->interface_count;
3597 for (i = 0; i < k->interface_count; i++) {
3598 ic = k->interfaces [i];
3600 mono_class_init (ic);
3602 if (max_iid < ic->interface_id)
3603 max_iid = ic->interface_id;
3605 ifaces = mono_class_get_implemented_interfaces (k, &error);
3606 if (!mono_error_ok (&error)) {
3607 char *name = mono_type_get_full_name (k);
3608 mono_class_set_type_load_failure (klass, "Error getting the interfaces of %s due to %s", name, mono_error_get_message (&error));
3610 mono_error_cleanup (&error);
3615 num_ifaces += ifaces->len;
3616 for (i = 0; i < ifaces->len; ++i) {
3617 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3618 if (max_iid < ic->interface_id)
3619 max_iid = ic->interface_id;
3621 ifaces_array [j] = ifaces;
3625 for (i = 0; i < num_array_interfaces; ++i) {
3626 ic = array_interfaces [i];
3627 mono_class_init (ic);
3628 if (max_iid < ic->interface_id)
3629 max_iid = ic->interface_id;
3632 if (MONO_CLASS_IS_INTERFACE (klass)) {
3634 if (max_iid < klass->interface_id)
3635 max_iid = klass->interface_id;
3638 /* compute vtable offset for interfaces */
3639 interfaces_full = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3640 interface_offsets_full = (int *)g_malloc (sizeof (int) * num_ifaces);
3642 for (i = 0; i < num_ifaces; i++)
3643 interface_offsets_full [i] = -1;
3645 /* skip the current class */
3646 for (j = 0; j < klass->idepth - 1; j++) {
3647 k = klass->supertypes [j];
3648 ifaces = ifaces_array [j];
3651 for (i = 0; i < ifaces->len; ++i) {
3653 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3655 /*Force the sharing of interface offsets between parent and subtypes.*/
3656 io = mono_class_interface_offset (k, ic);
3658 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3663 g_assert (klass == klass->supertypes [klass->idepth - 1]);
3664 ifaces = ifaces_array [klass->idepth - 1];
3666 for (i = 0; i < ifaces->len; ++i) {
3668 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3669 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3671 count = count_virtual_methods (ic);
3673 char *name = mono_type_get_full_name (ic);
3674 mono_class_set_type_load_failure (klass, "Error calculating interface offset of %s", name);
3683 if (MONO_CLASS_IS_INTERFACE (klass))
3684 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, klass, cur_slot, TRUE);
3686 if (num_array_interfaces) {
3687 if (is_enumerator) {
3688 int ienumerator_idx = find_array_interface (klass, "IEnumerator`1");
3689 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ienumerator_idx]);
3690 g_assert (ienumerator_offset >= 0);
3691 for (i = 0; i < num_array_interfaces; ++i) {
3692 ic = array_interfaces [i];
3693 if (strcmp (ic->name, "IEnumerator`1") == 0)
3694 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3696 g_assert_not_reached ();
3697 /*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);*/
3700 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3701 int ilist_iface_idx = find_array_interface (klass, "IList`1");
3702 MonoClass* ilist_class = klass->interfaces [ilist_iface_idx];
3703 int ireadonlylist_iface_idx = find_array_interface (klass, "IReadOnlyList`1");
3704 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? klass->interfaces [ireadonlylist_iface_idx] : NULL;
3705 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3706 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3707 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3708 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ilist_iface_idx]);
3709 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3710 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3711 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ireadonlylist_iface_idx]) : -1;
3712 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3713 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3714 for (i = 0; i < num_array_interfaces; ++i) {
3716 ic = array_interfaces [i];
3717 if (mono_class_get_generic_class (ic)->container_class == mono_defaults.generic_ilist_class)
3718 offset = ilist_offset;
3719 else if (strcmp (ic->name, "ICollection`1") == 0)
3720 offset = icollection_offset;
3721 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3722 offset = ienumerable_offset;
3723 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3724 offset = ireadonlylist_offset;
3725 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3726 offset = ireadonlycollection_offset;
3728 g_assert_not_reached ();
3729 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3730 /*g_print ("type %s has %s offset at %d (%s)\n", klass->name, ic->name, offset, klass->interfaces [0]->name);*/
3735 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3736 if (interface_offsets_full [i] != -1)
3737 interface_offsets_count ++;
3740 /* Publish the data */
3741 klass->max_interface_id = max_iid;
3743 * We might get called multiple times:
3744 * - mono_class_init ()
3745 * - mono_class_setup_vtable ().
3746 * - mono_class_setup_interface_offsets ().
3747 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3748 * means we have to overwrite those when called from other places (#4440).
3750 if (klass->interfaces_packed) {
3752 g_assert (klass->interface_offsets_count == interface_offsets_count);
3756 klass->interface_offsets_count = interface_offsets_count;
3757 klass->interfaces_packed = (MonoClass **)mono_class_alloc (klass, sizeof (MonoClass*) * interface_offsets_count);
3758 klass->interface_offsets_packed = (guint16 *)mono_class_alloc (klass, sizeof (guint16) * interface_offsets_count);
3759 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3760 #ifdef COMPRESSED_INTERFACE_BITMAP
3761 bitmap = g_malloc0 (bsize);
3763 bitmap = (uint8_t *)mono_class_alloc0 (klass, bsize);
3765 for (i = 0; i < interface_offsets_count; i++) {
3766 guint32 id = interfaces_full [i]->interface_id;
3767 bitmap [id >> 3] |= (1 << (id & 7));
3768 klass->interfaces_packed [i] = interfaces_full [i];
3769 klass->interface_offsets_packed [i] = interface_offsets_full [i];
3770 /*if (num_array_interfaces)
3771 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]);*/
3773 #ifdef COMPRESSED_INTERFACE_BITMAP
3774 i = mono_compress_bitmap (NULL, bitmap, bsize);
3775 klass->interface_bitmap = mono_class_alloc0 (klass, i);
3776 mono_compress_bitmap (klass->interface_bitmap, bitmap, bsize);
3779 klass->interface_bitmap = bitmap;
3783 mono_loader_unlock ();
3785 g_free (interfaces_full);
3786 g_free (interface_offsets_full);
3787 g_free (array_interfaces);
3788 for (i = 0; i < klass->idepth; i++) {
3789 ifaces = ifaces_array [i];
3791 g_ptr_array_free (ifaces, TRUE);
3793 g_free (ifaces_array);
3795 //printf ("JUST DONE: ");
3796 //print_implemented_interfaces (klass);
3802 * Setup interface offsets for interfaces.
3804 * - klass->max_interface_id
3805 * - klass->interface_offsets_count
3806 * - klass->interfaces_packed
3807 * - klass->interface_offsets_packed
3808 * - klass->interface_bitmap
3810 * This function can fail @class.
3813 mono_class_setup_interface_offsets (MonoClass *klass)
3815 setup_interface_offsets (klass, 0, FALSE);
3818 /*Checks if @klass has @parent as one of it's parents type gtd
3822 * Bar<T> : Foo<Bar<Bar<T>>>
3826 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3828 klass = mono_class_get_generic_type_definition (klass);
3829 parent = mono_class_get_generic_type_definition (parent);
3830 mono_class_setup_supertypes (klass);
3831 mono_class_setup_supertypes (parent);
3833 return klass->idepth >= parent->idepth &&
3834 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3838 mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup)
3840 MonoGenericInst *ginst;
3843 if (!mono_class_is_ginst (klass)) {
3844 mono_class_setup_vtable_full (klass, in_setup);
3845 return !mono_class_has_failure (klass);
3848 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup);
3849 if (mono_class_set_type_load_failure_causedby_class (klass, mono_class_get_generic_class (klass)->container_class, "Failed to load generic definition vtable"))
3852 ginst = mono_class_get_generic_class (klass)->context.class_inst;
3853 for (i = 0; i < ginst->type_argc; ++i) {
3855 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3857 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3858 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3859 if (mono_class_has_gtd_parent (klass, arg) || mono_class_has_gtd_parent (arg, klass))
3861 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3862 mono_class_set_type_load_failure (klass, "Failed to load generic parameter %d", i);
3870 * mono_class_setup_vtable:
3872 * Creates the generic vtable of CLASS.
3873 * Initializes the following fields in MonoClass:
3876 * Plus all the fields initialized by setup_interface_offsets ().
3877 * If there is an error during vtable construction, klass->has_failure
3878 * is set and details are stored in a MonoErrorBoxed.
3880 * LOCKING: Acquires the loader lock.
3883 mono_class_setup_vtable (MonoClass *klass)
3885 mono_class_setup_vtable_full (klass, NULL);
3889 mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
3892 MonoMethod **overrides;
3893 MonoGenericContext *context;
3901 if (MONO_CLASS_IS_INTERFACE (klass)) {
3902 /* This sets method->slot for all methods if this is an interface */
3903 mono_class_setup_methods (klass);
3907 if (mono_class_has_failure (klass))
3910 if (g_list_find (in_setup, klass))
3913 mono_loader_lock ();
3915 if (klass->vtable) {
3916 mono_loader_unlock ();
3920 mono_stats.generic_vtable_count ++;
3921 in_setup = g_list_prepend (in_setup, klass);
3923 if (mono_class_is_ginst (klass)) {
3924 if (!mono_class_check_vtable_constraints (klass, in_setup)) {
3925 mono_loader_unlock ();
3926 g_list_remove (in_setup, klass);
3930 context = mono_class_get_context (klass);
3931 type_token = mono_class_get_generic_class (klass)->container_class->type_token;
3933 context = (MonoGenericContext *) mono_class_try_get_generic_container (klass); //FIXME is this a case of a try?
3934 type_token = klass->type_token;
3937 if (image_is_dynamic (klass->image)) {
3938 /* Generic instances can have zero method overrides without causing any harm.
3939 * This is true since we don't do layout all over again for them, we simply inflate
3940 * the layout of the parent.
3942 mono_reflection_get_dynamic_overrides (klass, &overrides, &onum, &error);
3943 if (!is_ok (&error)) {
3944 mono_loader_unlock ();
3945 g_list_remove (in_setup, klass);
3946 mono_class_set_type_load_failure (klass, "Could not load list of method overrides due to %s", mono_error_get_message (&error));
3947 mono_error_cleanup (&error);
3951 /* The following call fails if there are missing methods in the type */
3952 /* FIXME it's probably a good idea to avoid this for generic instances. */
3953 ok = mono_class_get_overrides_full (klass->image, type_token, &overrides, &onum, context);
3957 mono_class_setup_vtable_general (klass, overrides, onum, in_setup);
3959 mono_class_set_type_load_failure (klass, "Could not load list of method overrides");
3963 mono_loader_unlock ();
3964 g_list_remove (in_setup, klass);
3969 #define DEBUG_INTERFACE_VTABLE_CODE 0
3970 #define TRACE_INTERFACE_VTABLE_CODE 0
3971 #define VERIFY_INTERFACE_VTABLE_CODE 0
3972 #define VTABLE_SELECTOR (1)
3974 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3975 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3976 if (!(VTABLE_SELECTOR)) break; \
3980 #define DEBUG_INTERFACE_VTABLE(stmt)
3983 #if TRACE_INTERFACE_VTABLE_CODE
3984 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3985 if (!(VTABLE_SELECTOR)) break; \
3989 #define TRACE_INTERFACE_VTABLE(stmt)
3992 #if VERIFY_INTERFACE_VTABLE_CODE
3993 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3994 if (!(VTABLE_SELECTOR)) break; \
3998 #define VERIFY_INTERFACE_VTABLE(stmt)
4002 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
4004 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
4008 GString *res = g_string_new ("");
4010 g_string_append_c (res, '(');
4011 for (i = 0; i < sig->param_count; ++i) {
4013 g_string_append_c (res, ',');
4014 mono_type_get_desc (res, sig->params [i], include_namespace);
4016 g_string_append (res, ")=>");
4017 if (sig->ret != NULL) {
4018 mono_type_get_desc (res, sig->ret, include_namespace);
4020 g_string_append (res, "NULL");
4023 g_string_free (res, FALSE);
4027 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
4028 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
4029 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
4030 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
4038 is_wcf_hack_disabled (void)
4040 static gboolean disabled;
4041 static gboolean inited = FALSE;
4043 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
4050 check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
4052 MonoMethodSignature *cmsig, *imsig;
4053 if (strcmp (im->name, cm->name) == 0) {
4054 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
4055 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
4058 if (! slot_is_empty) {
4059 if (require_newslot) {
4060 if (! interface_is_explicitly_implemented_by_class) {
4061 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
4064 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4065 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
4069 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
4072 cmsig = mono_method_signature (cm);
4073 imsig = mono_method_signature (im);
4074 if (!cmsig || !imsig) {
4075 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
4079 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4080 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
4081 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4082 TRACE_INTERFACE_VTABLE (printf ("]"));
4085 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
4086 if (mono_security_core_clr_enabled ())
4087 mono_security_core_clr_check_override (klass, cm, im);
4089 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
4090 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4091 char *body_name = mono_method_full_name (cm, TRUE);
4092 char *decl_name = mono_method_full_name (im, TRUE);
4093 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4101 MonoClass *ic = im->klass;
4102 const char *ic_name_space = ic->name_space;
4103 const char *ic_name = ic->name;
4106 if (! require_newslot) {
4107 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
4110 if (cm->klass->rank == 0) {
4111 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
4114 cmsig = mono_method_signature (cm);
4115 imsig = mono_method_signature (im);
4116 if (!cmsig || !imsig) {
4117 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
4121 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4122 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
4123 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4124 TRACE_INTERFACE_VTABLE (printf ("]"));
4127 if (mono_class_get_image (ic) != mono_defaults.corlib) {
4128 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
4131 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
4132 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
4135 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))) {
4136 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
4140 subname = strstr (cm->name, ic_name_space);
4141 if (subname != cm->name) {
4142 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
4145 subname += strlen (ic_name_space);
4146 if (subname [0] != '.') {
4147 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
4151 if (strstr (subname, ic_name) != subname) {
4152 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
4155 subname += strlen (ic_name);
4156 if (subname [0] != '.') {
4157 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
4161 if (strcmp (subname, im->name) != 0) {
4162 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
4166 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
4167 if (mono_security_core_clr_enabled ())
4168 mono_security_core_clr_check_override (klass, cm, im);
4170 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
4171 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4172 char *body_name = mono_method_full_name (cm, TRUE);
4173 char *decl_name = mono_method_full_name (im, TRUE);
4174 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4184 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
4186 foreach_override (gpointer key, gpointer value, gpointer user_data) {
4187 MonoMethod *method = key;
4188 MonoMethod *override = value;
4189 MonoClass *method_class = mono_method_get_class (method);
4190 MonoClass *override_class = mono_method_get_class (override);
4192 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
4193 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
4194 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
4197 print_overrides (GHashTable *override_map, const char *message) {
4199 printf ("Override map \"%s\" START:\n", message);
4200 g_hash_table_foreach (override_map, foreach_override, NULL);
4201 printf ("Override map \"%s\" END.\n", message);
4203 printf ("Override map \"%s\" EMPTY.\n", message);
4207 print_vtable_full (MonoClass *klass, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
4208 char *full_name = mono_type_full_name (&klass->byval_arg);
4212 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
4214 if (print_interfaces) {
4215 print_implemented_interfaces (klass);
4216 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
4219 if (klass->parent) {
4220 parent_size = klass->parent->vtable_size;
4224 for (i = 0; i < size; ++i) {
4225 MonoMethod *cm = vtable [i];
4226 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
4227 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
4229 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
4237 #if VERIFY_INTERFACE_VTABLE_CODE
4239 mono_method_try_get_vtable_index (MonoMethod *method)
4241 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4242 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4243 if (imethod->declaring->is_generic)
4244 return imethod->declaring->slot;
4246 return method->slot;
4250 mono_class_verify_vtable (MonoClass *klass)
4253 char *full_name = mono_type_full_name (&klass->byval_arg);
4255 printf ("*** Verifying VTable of class '%s' \n", full_name);
4259 if (!klass->methods)
4262 count = mono_class_method_count (klass);
4263 for (i = 0; i < count; ++i) {
4264 MonoMethod *cm = klass->methods [i];
4267 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4271 full_name = mono_method_full_name (cm, TRUE);
4273 slot = mono_method_try_get_vtable_index (cm);
4275 if (slot >= klass->vtable_size) {
4276 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, klass->vtable_size);
4280 if (slot >= 0 && klass->vtable [slot] != cm && (klass->vtable [slot])) {
4281 char *other_name = klass->vtable [slot] ? mono_method_full_name (klass->vtable [slot], TRUE) : g_strdup ("[null value]");
4282 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4283 g_free (other_name);
4286 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4293 print_unimplemented_interface_method_info (MonoClass *klass, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum)
4296 char *method_signature;
4299 for (index = 0; index < onum; ++index) {
4300 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)", im_slot, overrides [index*2+1]->name,
4301 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4303 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4304 type_name = mono_type_full_name (&klass->byval_arg);
4305 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s",
4306 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4307 g_free (method_signature);
4309 mono_class_setup_methods (klass);
4310 if (mono_class_has_failure (klass)) {
4311 char *name = mono_type_get_full_name (klass);
4312 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods", name);
4316 mcount = mono_class_get_method_count (klass);
4317 for (index = 0; index < mcount; ++index) {
4318 MonoMethod *cm = klass->methods [index];
4319 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4321 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)", cm->name, method_signature);
4322 g_free (method_signature);
4327 mono_method_get_method_definition (MonoMethod *method)
4329 while (method->is_inflated)
4330 method = ((MonoMethodInflated*)method)->declaring;
4335 verify_class_overrides (MonoClass *klass, MonoMethod **overrides, int onum)
4339 for (i = 0; i < onum; ++i) {
4340 MonoMethod *decl = overrides [i * 2];
4341 MonoMethod *body = overrides [i * 2 + 1];
4343 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (klass)) {
4344 mono_class_set_type_load_failure (klass, "Method belongs to a different class than the declared one");
4348 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4349 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4350 mono_class_set_type_load_failure (klass, "Method must not be static to override a base type");
4352 mono_class_set_type_load_failure (klass, "Method must be virtual to override a base type");
4356 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4357 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4358 mono_class_set_type_load_failure (klass, "Cannot override a static method in a base type");
4360 mono_class_set_type_load_failure (klass, "Cannot override a non virtual method in a base type");
4364 if (!mono_class_is_assignable_from_slow (decl->klass, klass)) {
4365 mono_class_set_type_load_failure (klass, "Method overrides a class or interface that is not extended or implemented by this type");
4369 body = mono_method_get_method_definition (body);
4370 decl = mono_method_get_method_definition (decl);
4372 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4373 char *body_name = mono_method_full_name (body, TRUE);
4374 char *decl_name = mono_method_full_name (decl, TRUE);
4375 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4385 mono_class_need_stelemref_method (MonoClass *klass)
4387 return klass->rank == 1 && MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg);
4391 * LOCKING: this is supposed to be called with the loader lock held.
4394 mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int onum, GList *in_setup)
4398 MonoMethod **vtable;
4399 int i, max_vtsize = 0, cur_slot = 0;
4401 GPtrArray *ifaces = NULL;
4402 GHashTable *override_map = NULL;
4404 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4405 int first_non_interface_slot;
4407 GSList *virt_methods = NULL, *l;
4408 int stelemref_slot = 0;
4413 if (overrides && !verify_class_overrides (klass, overrides, onum))
4416 ifaces = mono_class_get_implemented_interfaces (klass, &error);
4417 if (!mono_error_ok (&error)) {
4418 char *name = mono_type_get_full_name (klass);
4419 mono_class_set_type_load_failure (klass, "Could not resolve %s interfaces due to %s", name, mono_error_get_message (&error));
4421 mono_error_cleanup (&error);
4423 } else if (ifaces) {
4424 for (i = 0; i < ifaces->len; i++) {
4425 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
4426 max_vtsize += mono_class_get_method_count (ic);
4428 g_ptr_array_free (ifaces, TRUE);
4432 if (klass->parent) {
4433 mono_class_init (klass->parent);
4434 mono_class_setup_vtable_full (klass->parent, in_setup);
4436 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class failed to load"))
4439 max_vtsize += klass->parent->vtable_size;
4440 cur_slot = klass->parent->vtable_size;
4443 max_vtsize += mono_class_get_method_count (klass);
4445 /*Array have a slot for stelemref*/
4446 if (mono_class_need_stelemref_method (klass)) {
4447 stelemref_slot = cur_slot;
4452 vtable = (MonoMethod **)alloca (sizeof (gpointer) * max_vtsize);
4453 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4455 /* printf ("METAINIT %s.%s\n", klass->name_space, klass->name); */
4457 cur_slot = setup_interface_offsets (klass, cur_slot, TRUE);
4458 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4461 max_iid = klass->max_interface_id;
4462 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4464 /* Optimized version for generic instances */
4465 if (mono_class_is_ginst (klass)) {
4467 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4470 mono_class_setup_vtable_full (gklass, in_setup);
4471 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Could not load generic definition"))
4474 tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * gklass->vtable_size);
4475 klass->vtable_size = gklass->vtable_size;
4476 for (i = 0; i < gklass->vtable_size; ++i)
4477 if (gklass->vtable [i]) {
4478 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], klass, mono_class_get_context (klass), &error);
4479 if (!mono_error_ok (&error)) {
4480 mono_class_set_type_load_failure (klass, "Could not inflate method due to %s", mono_error_get_message (&error));
4481 mono_error_cleanup (&error);
4485 tmp [i]->slot = gklass->vtable [i]->slot;
4487 mono_memory_barrier ();
4488 klass->vtable = tmp;
4490 /* Have to set method->slot for abstract virtual methods */
4491 if (klass->methods && gklass->methods) {
4492 int mcount = mono_class_get_method_count (klass);
4493 for (i = 0; i < mcount; ++i)
4494 if (klass->methods [i]->slot == -1)
4495 klass->methods [i]->slot = gklass->methods [i]->slot;
4501 if (klass->parent && klass->parent->vtable_size) {
4502 MonoClass *parent = klass->parent;
4505 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4507 // Also inherit parent interface vtables, just as a starting point.
4508 // This is needed otherwise bug-77127.exe fails when the property methods
4509 // have different names in the iterface and the class, because for child
4510 // classes the ".override" information is not used anymore.
4511 for (i = 0; i < parent->interface_offsets_count; i++) {
4512 MonoClass *parent_interface = parent->interfaces_packed [i];
4513 int interface_offset = mono_class_interface_offset (klass, parent_interface);
4514 /*FIXME this is now dead code as this condition will never hold true.
4515 Since interface offsets are inherited then the offset of an interface implemented
4516 by a parent will never be the out of it's vtable boundary.
4518 if (interface_offset >= parent->vtable_size) {
4519 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4522 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4523 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4524 int mcount = mono_class_get_method_count (parent_interface);
4525 for (j = 0; j < mcount && !mono_class_has_failure (klass); j++) {
4526 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4527 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4528 parent_interface_offset + j, parent_interface_offset, j,
4529 interface_offset + j, interface_offset, j));
4536 /*Array have a slot for stelemref*/
4537 if (mono_class_need_stelemref_method (klass)) {
4538 MonoMethod *method = mono_marshal_get_virtual_stelemref (klass);
4540 method->slot = stelemref_slot;
4542 g_assert (method->slot == stelemref_slot);
4544 vtable [stelemref_slot] = method;
4547 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4548 /* override interface methods */
4549 for (i = 0; i < onum; i++) {
4550 MonoMethod *decl = overrides [i*2];
4551 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4553 dslot = mono_method_get_vtable_slot (decl);
4555 mono_class_set_type_load_failure (klass, "");
4559 dslot += mono_class_interface_offset (klass, decl->klass);
4560 vtable [dslot] = overrides [i*2 + 1];
4561 vtable [dslot]->slot = dslot;
4563 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4565 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4567 if (mono_security_core_clr_enabled ())
4568 mono_security_core_clr_check_override (klass, vtable [dslot], decl);
4571 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4572 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4575 * Create a list of virtual methods to avoid calling
4576 * mono_class_get_virtual_methods () which is slow because of the metadata
4580 gpointer iter = NULL;
4583 virt_methods = NULL;
4584 while ((cm = mono_class_get_virtual_methods (klass, &iter))) {
4585 virt_methods = g_slist_prepend (virt_methods, cm);
4587 if (mono_class_has_failure (klass))
4591 // Loop on all implemented interfaces...
4592 for (i = 0; i < klass->interface_offsets_count; i++) {
4593 MonoClass *parent = klass->parent;
4595 gboolean interface_is_explicitly_implemented_by_class;
4598 ic = klass->interfaces_packed [i];
4599 ic_offset = mono_class_interface_offset (klass, ic);
4601 mono_class_setup_methods (ic);
4602 if (mono_class_has_failure (ic))
4605 // Check if this interface is explicitly implemented (instead of just inherited)
4606 if (parent != NULL) {
4607 int implemented_interfaces_index;
4608 interface_is_explicitly_implemented_by_class = FALSE;
4609 for (implemented_interfaces_index = 0; implemented_interfaces_index < klass->interface_count; implemented_interfaces_index++) {
4610 if (ic == klass->interfaces [implemented_interfaces_index]) {
4611 interface_is_explicitly_implemented_by_class = TRUE;
4616 interface_is_explicitly_implemented_by_class = TRUE;
4619 // Loop on all interface methods...
4620 int mcount = mono_class_get_method_count (ic);
4621 for (im_index = 0; im_index < mcount; im_index++) {
4622 MonoMethod *im = ic->methods [im_index];
4623 int im_slot = ic_offset + im->slot;
4624 MonoMethod *override_im = (override_map != NULL) ? (MonoMethod *)g_hash_table_lookup (override_map, im) : NULL;
4626 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4629 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4631 // If there is an explicit implementation, just use it right away,
4632 // otherwise look for a matching method
4633 if (override_im == NULL) {
4637 // First look for a suitable method among the class methods
4638 for (l = virt_methods; l; l = l->next) {
4639 cm = (MonoMethod *)l->data;
4640 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)));
4641 if (check_interface_method_override (klass, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
4642 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4643 vtable [im_slot] = cm;
4644 /* Why do we need this? */
4649 TRACE_INTERFACE_VTABLE (printf ("\n"));
4650 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4654 // If the slot is still empty, look in all the inherited virtual methods...
4655 if ((vtable [im_slot] == NULL) && klass->parent != NULL) {
4656 MonoClass *parent = klass->parent;
4657 // Reverse order, so that last added methods are preferred
4658 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4659 MonoMethod *cm = parent->vtable [cm_index];
4661 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));
4662 if ((cm != NULL) && check_interface_method_override (klass, im, cm, FALSE, FALSE, TRUE)) {
4663 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4664 vtable [im_slot] = cm;
4665 /* Why do we need this? */
4671 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4673 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4677 g_assert (vtable [im_slot] == override_im);
4682 // If the class is not abstract, check that all its interface slots are full.
4683 // The check is done here and not directly at the end of the loop above because
4684 // it can happen (for injected generic array interfaces) that the same slot is
4685 // processed multiple times (those interfaces have overlapping slots), and it
4686 // will not always be the first pass the one that fills the slot.
4687 if (!mono_class_is_abstract (klass)) {
4688 for (i = 0; i < klass->interface_offsets_count; i++) {
4692 ic = klass->interfaces_packed [i];
4693 ic_offset = mono_class_interface_offset (klass, ic);
4695 int mcount = mono_class_get_method_count (ic);
4696 for (im_index = 0; im_index < mcount; im_index++) {
4697 MonoMethod *im = ic->methods [im_index];
4698 int im_slot = ic_offset + im->slot;
4700 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4703 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4704 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4705 if (vtable [im_slot] == NULL) {
4706 print_unimplemented_interface_method_info (klass, ic, im, im_slot, overrides, onum);
4713 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4714 for (l = virt_methods; l; l = l->next) {
4715 cm = (MonoMethod *)l->data;
4717 * If the method is REUSE_SLOT, we must check in the
4718 * base class for a method to override.
4720 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4722 for (k = klass->parent; k ; k = k->parent) {
4727 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4728 MonoMethodSignature *cmsig, *m1sig;
4730 cmsig = mono_method_signature (cm);
4731 m1sig = mono_method_signature (m1);
4733 if (!cmsig || !m1sig) {
4734 /* FIXME proper error message */
4735 mono_class_set_type_load_failure (klass, "");
4739 if (!strcmp(cm->name, m1->name) &&
4740 mono_metadata_signature_equal (cmsig, m1sig)) {
4742 if (mono_security_core_clr_enabled ())
4743 mono_security_core_clr_check_override (klass, cm, m1);
4745 slot = mono_method_get_vtable_slot (m1);
4749 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4750 char *body_name = mono_method_full_name (cm, TRUE);
4751 char *decl_name = mono_method_full_name (m1, TRUE);
4752 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4758 g_assert (cm->slot < max_vtsize);
4760 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4761 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4762 mono_method_full_name (m1, 1), m1,
4763 mono_method_full_name (cm, 1), cm));
4764 g_hash_table_insert (override_map, m1, cm);
4768 if (mono_class_has_failure (k))
4778 /*Non final newslot methods must be given a non-interface vtable slot*/
4779 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4783 cm->slot = cur_slot++;
4785 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4786 vtable [cm->slot] = cm;
4789 /* override non interface methods */
4790 for (i = 0; i < onum; i++) {
4791 MonoMethod *decl = overrides [i*2];
4792 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4793 g_assert (decl->slot != -1);
4794 vtable [decl->slot] = overrides [i*2 + 1];
4795 overrides [i * 2 + 1]->slot = decl->slot;
4797 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4798 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4799 mono_method_full_name (decl, 1), decl,
4800 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4801 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4803 if (mono_security_core_clr_enabled ())
4804 mono_security_core_clr_check_override (klass, vtable [decl->slot], decl);
4809 * If a method occupies more than one place in the vtable, and it is
4810 * overriden, then change the other occurances too.
4815 for (i = 0; i < max_vtsize; ++i)
4817 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4819 cm = (MonoMethod *)g_hash_table_lookup (override_map, vtable [i]);
4824 g_hash_table_destroy (override_map);
4825 override_map = NULL;
4828 g_slist_free (virt_methods);
4829 virt_methods = NULL;
4831 /* Ensure that all vtable slots are filled with concrete instance methods */
4832 if (!mono_class_is_abstract (klass)) {
4833 for (i = 0; i < cur_slot; ++i) {
4834 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4835 char *type_name = mono_type_get_full_name (klass);
4836 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4837 mono_class_set_type_load_failure (klass, "Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name);
4839 g_free (method_name);
4845 if (mono_class_is_ginst (klass)) {
4846 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4848 mono_class_init (gklass);
4850 klass->vtable_size = MAX (gklass->vtable_size, cur_slot);
4852 /* Check that the vtable_size value computed in mono_class_init () is correct */
4853 if (klass->vtable_size)
4854 g_assert (cur_slot == klass->vtable_size);
4855 klass->vtable_size = cur_slot;
4858 /* Try to share the vtable with our parent. */
4859 if (klass->parent && (klass->parent->vtable_size == klass->vtable_size) && (memcmp (klass->parent->vtable, vtable, sizeof (gpointer) * klass->vtable_size) == 0)) {
4860 mono_memory_barrier ();
4861 klass->vtable = klass->parent->vtable;
4863 MonoMethod **tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * klass->vtable_size);
4864 memcpy (tmp, vtable, sizeof (gpointer) * klass->vtable_size);
4865 mono_memory_barrier ();
4866 klass->vtable = tmp;
4869 DEBUG_INTERFACE_VTABLE (print_vtable_full (klass, klass->vtable, klass->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4870 if (mono_print_vtable) {
4873 print_implemented_interfaces (klass);
4875 for (i = 0; i <= max_iid; i++)
4876 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
4879 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&klass->byval_arg),
4880 klass->vtable_size, icount);
4882 for (i = 0; i < cur_slot; ++i) {
4887 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4888 mono_method_full_name (cm, TRUE));
4894 printf ("Interfaces %s.%s (max_iid = %d)\n", klass->name_space,
4895 klass->name, max_iid);
4897 for (i = 0; i < klass->interface_count; i++) {
4898 ic = klass->interfaces [i];
4899 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4900 mono_class_interface_offset (klass, ic),
4901 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4904 for (k = klass->parent; k ; k = k->parent) {
4905 for (i = 0; i < k->interface_count; i++) {
4906 ic = k->interfaces [i];
4907 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4908 mono_class_interface_offset (klass, ic),
4909 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4915 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (klass));
4920 char *name = mono_type_get_full_name (klass);
4921 mono_class_set_type_load_failure (klass, "VTable setup of type %s failed", name);
4924 g_hash_table_destroy (override_map);
4926 g_slist_free (virt_methods);
4931 * mono_method_get_vtable_slot:
4933 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4934 * LOCKING: Acquires the loader lock.
4936 * FIXME Use proper MonoError machinery here.
4939 mono_method_get_vtable_slot (MonoMethod *method)
4941 if (method->slot == -1) {
4942 mono_class_setup_vtable (method->klass);
4943 if (mono_class_has_failure (method->klass))
4945 if (method->slot == -1) {
4949 if (!mono_class_is_ginst (method->klass)) {
4950 g_assert (method->is_inflated);
4951 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4954 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4955 g_assert (mono_class_is_ginst (method->klass));
4956 gklass = mono_class_get_generic_class (method->klass)->container_class;
4957 mono_class_setup_methods (method->klass);
4958 g_assert (method->klass->methods);
4959 mcount = mono_class_get_method_count (method->klass);
4960 for (i = 0; i < mcount; ++i) {
4961 if (method->klass->methods [i] == method)
4964 g_assert (i < mcount);
4965 g_assert (gklass->methods);
4966 method->slot = gklass->methods [i]->slot;
4968 g_assert (method->slot != -1);
4970 return method->slot;
4974 * mono_method_get_vtable_index:
4977 * Returns the index into the runtime vtable to access the method or,
4978 * in the case of a virtual generic method, the virtual generic method
4979 * thunk. Returns -1 on failure.
4981 * FIXME Use proper MonoError machinery here.
4984 mono_method_get_vtable_index (MonoMethod *method)
4986 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4987 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4988 if (imethod->declaring->is_generic)
4989 return mono_method_get_vtable_slot (imethod->declaring);
4991 return mono_method_get_vtable_slot (method);
4994 static MonoMethod *default_ghc = NULL;
4995 static MonoMethod *default_finalize = NULL;
4996 static int finalize_slot = -1;
4997 static int ghc_slot = -1;
5000 initialize_object_slots (MonoClass *klass)
5005 if (klass == mono_defaults.object_class) {
5006 mono_class_setup_vtable (klass);
5007 for (i = 0; i < klass->vtable_size; ++i) {
5008 MonoMethod *cm = klass->vtable [i];
5010 if (!strcmp (cm->name, "GetHashCode"))
5012 else if (!strcmp (cm->name, "Finalize"))
5016 g_assert (ghc_slot > 0);
5017 default_ghc = klass->vtable [ghc_slot];
5019 g_assert (finalize_slot > 0);
5020 default_finalize = klass->vtable [finalize_slot];
5025 MonoMethod *array_method;
5027 } GenericArrayMethodInfo;
5029 static int generic_array_method_num = 0;
5030 static GenericArrayMethodInfo *generic_array_method_info = NULL;
5033 generic_array_methods (MonoClass *klass)
5035 int i, count_generic = 0, mcount;
5036 GList *list = NULL, *tmp;
5037 if (generic_array_method_num)
5038 return generic_array_method_num;
5039 mono_class_setup_methods (klass->parent); /*This is setting up System.Array*/
5040 g_assert (!mono_class_has_failure (klass->parent)); /*So hitting this assert is a huge problem*/
5041 mcount = mono_class_get_method_count (klass->parent);
5042 for (i = 0; i < mcount; i++) {
5043 MonoMethod *m = klass->parent->methods [i];
5044 if (!strncmp (m->name, "InternalArray__", 15)) {
5046 list = g_list_prepend (list, m);
5049 list = g_list_reverse (list);
5050 generic_array_method_info = (GenericArrayMethodInfo *)mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
5052 for (tmp = list; tmp; tmp = tmp->next) {
5053 const char *mname, *iname;
5055 MonoMethod *m = (MonoMethod *)tmp->data;
5056 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
5057 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
5059 generic_array_method_info [i].array_method = m;
5060 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
5061 iname = "System.Collections.Generic.ICollection`1.";
5062 mname = m->name + 27;
5063 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
5064 iname = "System.Collections.Generic.IEnumerable`1.";
5065 mname = m->name + 27;
5066 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
5067 iname = "System.Collections.Generic.IReadOnlyList`1.";
5068 mname = m->name + strlen (ireadonlylist_prefix);
5069 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
5070 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
5071 mname = m->name + strlen (ireadonlycollection_prefix);
5072 } else if (!strncmp (m->name, "InternalArray__", 15)) {
5073 iname = "System.Collections.Generic.IList`1.";
5074 mname = m->name + 15;
5076 g_assert_not_reached ();
5079 name = (gchar *)mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
5080 strcpy (name, iname);
5081 strcpy (name + strlen (iname), mname);
5082 generic_array_method_info [i].name = name;
5085 /*g_print ("array generic methods: %d\n", count_generic);*/
5087 generic_array_method_num = count_generic;
5089 return generic_array_method_num;
5093 setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos)
5095 MonoGenericContext tmp_context;
5098 tmp_context.class_inst = NULL;
5099 tmp_context.method_inst = mono_class_get_generic_class (iface)->context.class_inst;
5100 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
5102 for (i = 0; i < generic_array_method_num; i++) {
5104 MonoMethod *m = generic_array_method_info [i].array_method;
5105 MonoMethod *inflated;
5107 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
5108 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
5109 methods [pos++] = mono_marshal_get_generic_array_helper (klass, iface, generic_array_method_info [i].name, inflated);
5114 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
5116 int null_length = strlen ("(null)");
5117 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
5118 char *s = (char *)mono_image_alloc (image, len);
5121 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
5122 g_assert (result == len - 1);
5129 * @klass: the class to initialize
5131 * Compute the instance_size, class_size and other infos that cannot be
5132 * computed at mono_class_get() time. Also compute vtable_size if possible.
5133 * Returns TRUE on success or FALSE if there was a problem in loading
5134 * the type (incorrect assemblies, missing assemblies, methods, etc).
5135 * Initializes the following fields in @klass:
5136 * - all the fields initialized by mono_class_init_sizes ()
5141 * LOCKING: Acquires the loader lock.
5144 mono_class_init (MonoClass *klass)
5146 int i, vtable_size = 0, array_method_count = 0;
5147 MonoCachedClassInfo cached_info;
5148 gboolean has_cached_info;
5149 gboolean locked = FALSE;
5150 gboolean ghcimpl = FALSE;
5151 gboolean has_cctor = FALSE;
5152 int first_iface_slot = 0;
5156 /* Double-checking locking pattern */
5157 if (klass->inited || mono_class_has_failure (klass))
5158 return !mono_class_has_failure (klass);
5160 /*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/
5163 * This function can recursively call itself.
5165 GSList *init_list = (GSList *)mono_native_tls_get_value (init_pending_tls_id);
5166 if (g_slist_find (init_list, klass)) {
5167 mono_class_set_type_load_failure (klass, "Recursive type definition detected");
5170 init_list = g_slist_prepend (init_list, klass);
5171 mono_native_tls_set_value (init_pending_tls_id, init_list);
5174 * We want to avoid doing complicated work inside locks, so we compute all the required
5175 * information and write it to @klass inside a lock.
5178 if (mono_verifier_is_enabled_for_class (klass) && !mono_verifier_verify_class (klass)) {
5179 mono_class_set_type_load_failure (klass, "%s", concat_two_strings_with_zero (klass->image, klass->name, klass->image->assembly_name));
5183 if (klass->byval_arg.type == MONO_TYPE_ARRAY || klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5184 MonoClass *element_class = klass->element_class;
5185 if (!element_class->inited)
5186 mono_class_init (element_class);
5187 if (mono_class_set_type_load_failure_causedby_class (klass, element_class, "Could not load array element class"))
5191 mono_stats.initialized_class_count++;
5193 if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic) {
5194 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5196 mono_class_init (gklass);
5197 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic Type Definition failed to init"))
5200 mono_class_setup_interface_id (klass);
5203 if (klass->parent && !klass->parent->inited)
5204 mono_class_init (klass->parent);
5206 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
5208 /* Compute instance size etc. */
5209 init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
5210 if (mono_class_has_failure (klass))
5213 mono_class_setup_supertypes (klass);
5216 initialize_object_slots (klass);
5219 * Initialize the rest of the data without creating a generic vtable if possible.
5220 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5221 * also avoid computing a generic vtable.
5223 if (has_cached_info) {
5225 vtable_size = cached_info.vtable_size;
5226 ghcimpl = cached_info.ghcimpl;
5227 has_cctor = cached_info.has_cctor;
5228 } else if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5229 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5230 * The first slot if for array with.
5232 static int szarray_vtable_size[2] = { 0 };
5234 int slot = MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg) ? 0 : 1;
5237 if (!szarray_vtable_size [slot]) {
5238 mono_class_setup_vtable (klass);
5239 szarray_vtable_size [slot] = klass->vtable_size;
5240 vtable_size = klass->vtable_size;
5242 vtable_size = szarray_vtable_size[slot];
5244 } else if (mono_class_is_ginst (klass) && !MONO_CLASS_IS_INTERFACE (klass)) {
5245 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5247 /* Generic instance case */
5248 ghcimpl = gklass->ghcimpl;
5249 has_cctor = gklass->has_cctor;
5251 mono_class_setup_vtable (gklass);
5252 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to init"))
5255 vtable_size = gklass->vtable_size;
5259 /* ghcimpl is not currently used
5261 if (klass->parent) {
5262 MonoMethod *cmethod = klass->vtable [ghc_slot];
5263 if (cmethod->is_inflated)
5264 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5265 if (cmethod == default_ghc) {
5271 /* C# doesn't allow interfaces to have cctors */
5272 if (!MONO_CLASS_IS_INTERFACE (klass) || klass->image != mono_defaults.corlib) {
5273 MonoMethod *cmethod = NULL;
5275 if (mono_class_is_ginst (klass)) {
5276 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5278 /* Generic instance case */
5279 ghcimpl = gklass->ghcimpl;
5280 has_cctor = gklass->has_cctor;
5281 } else if (klass->type_token && !image_is_dynamic(klass->image)) {
5282 cmethod = find_method_in_metadata (klass, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5283 /* The find_method function ignores the 'flags' argument */
5284 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5287 mono_class_setup_methods (klass);
5288 if (mono_class_has_failure (klass))
5291 int mcount = mono_class_get_method_count (klass);
5292 for (i = 0; i < mcount; ++i) {
5293 MonoMethod *method = klass->methods [i];
5294 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5295 (strcmp (".cctor", method->name) == 0)) {
5305 array_method_count = 3 + (klass->rank > 1? 2: 1);
5307 if (klass->interface_count) {
5308 int count_generic = generic_array_methods (klass);
5309 array_method_count += klass->interface_count * count_generic;
5313 if (klass->parent) {
5314 if (!klass->parent->vtable_size)
5315 mono_class_setup_vtable (klass->parent);
5316 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class vtable failed to initialize"))
5318 g_assert (klass->parent->vtable_size);
5319 first_iface_slot = klass->parent->vtable_size;
5320 if (mono_class_need_stelemref_method (klass))
5325 * Do the actual changes to @klass inside the loader lock
5327 mono_loader_lock ();
5330 if (klass->inited || mono_class_has_failure (klass)) {
5331 mono_loader_unlock ();
5332 /* Somebody might have gotten in before us */
5333 return !mono_class_has_failure (klass);
5336 mono_stats.initialized_class_count++;
5338 if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic)
5339 mono_stats.generic_class_count++;
5341 if (mono_class_is_ginst (klass) || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
5342 klass->nested_classes_inited = TRUE;
5343 klass->ghcimpl = ghcimpl;
5344 klass->has_cctor = has_cctor;
5346 klass->vtable_size = vtable_size;
5347 if (has_cached_info) {
5348 klass->has_finalize = cached_info.has_finalize;
5349 klass->has_finalize_inited = TRUE;
5352 mono_class_set_method_count (klass, array_method_count);
5354 mono_loader_unlock ();
5357 setup_interface_offsets (klass, first_iface_slot, TRUE);
5359 if (mono_security_core_clr_enabled ())
5360 mono_security_core_clr_check_inheritance (klass);
5362 if (mono_class_is_ginst (klass) && !mono_verifier_class_is_valid_generic_instantiation (klass))
5363 mono_class_set_type_load_failure (klass, "Invalid generic instantiation");
5368 init_list = g_slist_remove (init_list, klass);
5369 mono_native_tls_set_value (init_pending_tls_id, init_list);
5371 /* Because of the double-checking locking pattern */
5372 mono_memory_barrier ();
5376 mono_loader_unlock ();
5378 return !mono_class_has_failure (klass);
5382 * mono_class_has_finalizer:
5384 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5388 mono_class_has_finalizer (MonoClass *klass)
5390 gboolean has_finalize = FALSE;
5392 if (klass->has_finalize_inited)
5393 return klass->has_finalize;
5395 /* Interfaces and valuetypes are not supposed to have finalizers */
5396 if (!(MONO_CLASS_IS_INTERFACE (klass) || klass->valuetype)) {
5397 MonoMethod *cmethod = NULL;
5399 if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5400 } else if (mono_class_is_ginst (klass)) {
5401 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5403 has_finalize = mono_class_has_finalizer (gklass);
5404 } else if (klass->parent && klass->parent->has_finalize) {
5405 has_finalize = TRUE;
5407 if (klass->parent) {
5409 * Can't search in metadata for a method named Finalize, because that
5410 * ignores overrides.
5412 mono_class_setup_vtable (klass);
5413 if (mono_class_has_failure (klass))
5416 cmethod = klass->vtable [finalize_slot];
5420 g_assert (klass->vtable_size > finalize_slot);
5422 if (klass->parent) {
5423 if (cmethod->is_inflated)
5424 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5425 if (cmethod != default_finalize)
5426 has_finalize = TRUE;
5432 mono_image_lock (klass->image);
5434 if (!klass->has_finalize_inited) {
5435 klass->has_finalize = has_finalize ? 1 : 0;
5437 mono_memory_barrier ();
5438 klass->has_finalize_inited = TRUE;
5441 mono_image_unlock (klass->image);
5443 return klass->has_finalize;
5447 mono_is_corlib_image (MonoImage *image)
5449 return image == mono_defaults.corlib;
5453 * LOCKING: this assumes the loader lock is held
5456 mono_class_setup_mono_type (MonoClass *klass)
5458 const char *name = klass->name;
5459 const char *nspace = klass->name_space;
5460 gboolean is_corlib = mono_is_corlib_image (klass->image);
5462 klass->this_arg.byref = 1;
5463 klass->this_arg.data.klass = klass;
5464 klass->this_arg.type = MONO_TYPE_CLASS;
5465 klass->byval_arg.data.klass = klass;
5466 klass->byval_arg.type = MONO_TYPE_CLASS;
5468 if (is_corlib && !strcmp (nspace, "System")) {
5469 if (!strcmp (name, "ValueType")) {
5471 * do not set the valuetype bit for System.ValueType.
5472 * klass->valuetype = 1;
5474 klass->blittable = TRUE;
5475 } else if (!strcmp (name, "Enum")) {
5477 * do not set the valuetype bit for System.Enum.
5478 * klass->valuetype = 1;
5480 klass->valuetype = 0;
5481 klass->enumtype = 0;
5482 } else if (!strcmp (name, "Object")) {
5483 klass->byval_arg.type = MONO_TYPE_OBJECT;
5484 klass->this_arg.type = MONO_TYPE_OBJECT;
5485 } else if (!strcmp (name, "String")) {
5486 klass->byval_arg.type = MONO_TYPE_STRING;
5487 klass->this_arg.type = MONO_TYPE_STRING;
5488 } else if (!strcmp (name, "TypedReference")) {
5489 klass->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5490 klass->this_arg.type = MONO_TYPE_TYPEDBYREF;
5494 if (klass->valuetype) {
5495 int t = MONO_TYPE_VALUETYPE;
5497 if (is_corlib && !strcmp (nspace, "System")) {
5500 if (!strcmp (name, "Boolean")) {
5501 t = MONO_TYPE_BOOLEAN;
5502 } else if (!strcmp(name, "Byte")) {
5504 klass->blittable = TRUE;
5508 if (!strcmp (name, "Char")) {
5513 if (!strcmp (name, "Double")) {
5515 klass->blittable = TRUE;
5519 if (!strcmp (name, "Int32")) {
5521 klass->blittable = TRUE;
5522 } else if (!strcmp(name, "Int16")) {
5524 klass->blittable = TRUE;
5525 } else if (!strcmp(name, "Int64")) {
5527 klass->blittable = TRUE;
5528 } else if (!strcmp(name, "IntPtr")) {
5530 klass->blittable = TRUE;
5534 if (!strcmp (name, "Single")) {
5536 klass->blittable = TRUE;
5537 } else if (!strcmp(name, "SByte")) {
5539 klass->blittable = TRUE;
5543 if (!strcmp (name, "UInt32")) {
5545 klass->blittable = TRUE;
5546 } else if (!strcmp(name, "UInt16")) {
5548 klass->blittable = TRUE;
5549 } else if (!strcmp(name, "UInt64")) {
5551 klass->blittable = TRUE;
5552 } else if (!strcmp(name, "UIntPtr")) {
5554 klass->blittable = TRUE;
5558 if (!strcmp (name, "TypedReference")) {
5559 t = MONO_TYPE_TYPEDBYREF;
5560 klass->blittable = TRUE;
5564 if (!strcmp (name, "Void")) {
5572 klass->byval_arg.type = (MonoTypeEnum)t;
5573 klass->this_arg.type = (MonoTypeEnum)t;
5576 if (MONO_CLASS_IS_INTERFACE (klass))
5577 klass->interface_id = mono_get_unique_iid (klass);
5582 * COM initialization is delayed until needed.
5583 * However when a [ComImport] attribute is present on a type it will trigger
5584 * the initialization. This is not a problem unless the BCL being executed
5585 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5588 init_com_from_comimport (MonoClass *klass)
5590 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5591 if (mono_security_core_clr_enabled ()) {
5592 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5593 if (!mono_security_core_clr_determine_platform_image (klass->image)) {
5594 /* but it can not be made available for application (i.e. user code) since all COM calls
5595 * are considered native calls. In this case we fail with a TypeLoadException (just like
5596 * Silverlight 2 does */
5597 mono_class_set_type_load_failure (klass, "");
5602 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5604 #endif /*DISABLE_COM*/
5607 * LOCKING: this assumes the loader lock is held
5610 mono_class_setup_parent (MonoClass *klass, MonoClass *parent)
5612 gboolean system_namespace;
5613 gboolean is_corlib = mono_is_corlib_image (klass->image);
5615 system_namespace = !strcmp (klass->name_space, "System") && is_corlib;
5617 /* if root of the hierarchy */
5618 if (system_namespace && !strcmp (klass->name, "Object")) {
5619 klass->parent = NULL;
5620 klass->instance_size = sizeof (MonoObject);
5623 if (!strcmp (klass->name, "<Module>")) {
5624 klass->parent = NULL;
5625 klass->instance_size = 0;
5629 if (!MONO_CLASS_IS_INTERFACE (klass)) {
5630 /* Imported COM Objects always derive from __ComObject. */
5632 if (MONO_CLASS_IS_IMPORT (klass)) {
5633 init_com_from_comimport (klass);
5634 if (parent == mono_defaults.object_class)
5635 parent = mono_class_get_com_object_class ();
5639 /* set the parent to something useful and safe, but mark the type as broken */
5640 parent = mono_defaults.object_class;
5641 mono_class_set_type_load_failure (klass, "");
5645 klass->parent = parent;
5647 if (mono_class_is_ginst (parent) && !parent->name) {
5649 * If the parent is a generic instance, we may get
5650 * called before it is fully initialized, especially
5651 * before it has its name.
5656 #ifndef DISABLE_REMOTING
5657 klass->marshalbyref = parent->marshalbyref;
5658 klass->contextbound = parent->contextbound;
5661 klass->delegate = parent->delegate;
5663 if (MONO_CLASS_IS_IMPORT (klass) || mono_class_is_com_object (parent))
5664 mono_class_set_is_com_object (klass);
5666 if (system_namespace) {
5667 #ifndef DISABLE_REMOTING
5668 if (klass->name [0] == 'M' && !strcmp (klass->name, "MarshalByRefObject"))
5669 klass->marshalbyref = 1;
5671 if (klass->name [0] == 'C' && !strcmp (klass->name, "ContextBoundObject"))
5672 klass->contextbound = 1;
5674 if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate"))
5675 klass->delegate = 1;
5678 if (klass->parent->enumtype || (mono_is_corlib_image (klass->parent->image) && (strcmp (klass->parent->name, "ValueType") == 0) &&
5679 (strcmp (klass->parent->name_space, "System") == 0)))
5680 klass->valuetype = 1;
5681 if (mono_is_corlib_image (klass->parent->image) && ((strcmp (klass->parent->name, "Enum") == 0) && (strcmp (klass->parent->name_space, "System") == 0))) {
5682 klass->valuetype = klass->enumtype = 1;
5684 /*klass->enumtype = klass->parent->enumtype; */
5686 /* initialize com types if COM interfaces are present */
5688 if (MONO_CLASS_IS_IMPORT (klass))
5689 init_com_from_comimport (klass);
5691 klass->parent = NULL;
5697 * mono_class_setup_supertypes:
5700 * Build the data structure needed to make fast type checks work.
5701 * This currently sets two fields in @class:
5702 * - idepth: distance between @class and System.Object in the type
5704 * - supertypes: array of classes: each element has a class in the hierarchy
5705 * starting from @class up to System.Object
5707 * LOCKING: Acquires the loader lock.
5710 mono_class_setup_supertypes (MonoClass *klass)
5713 MonoClass **supertypes;
5715 mono_atomic_load_acquire (supertypes, MonoClass **, &klass->supertypes);
5719 if (klass->parent && !klass->parent->supertypes)
5720 mono_class_setup_supertypes (klass->parent);
5722 idepth = klass->parent->idepth + 1;
5726 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, idepth);
5727 supertypes = (MonoClass **)mono_class_alloc0 (klass, sizeof (MonoClass *) * ms);
5729 if (klass->parent) {
5730 CHECKED_METADATA_WRITE_PTR ( supertypes [idepth - 1] , klass );
5733 for (supertype_idx = 0; supertype_idx < klass->parent->idepth; supertype_idx++)
5734 CHECKED_METADATA_WRITE_PTR ( supertypes [supertype_idx] , klass->parent->supertypes [supertype_idx] );
5736 CHECKED_METADATA_WRITE_PTR ( supertypes [0] , klass );
5739 mono_memory_barrier ();
5741 mono_loader_lock ();
5742 klass->idepth = idepth;
5743 /* Needed so idepth is visible before supertypes is set */
5744 mono_memory_barrier ();
5745 klass->supertypes = supertypes;
5746 mono_loader_unlock ();
5750 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5752 MonoClass *gtd = (MonoClass*)user_data;
5753 /* Only try to fix generic instances of @gtd */
5754 if (mono_class_get_generic_class (gclass)->container_class != gtd)
5757 /* Check if the generic instance has no parent. */
5758 if (gtd->parent && !gclass->parent)
5759 mono_generic_class_setup_parent (gclass, gtd);
5765 mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char *msg)
5767 mono_class_set_type_load_failure (klass, "%s", msg);
5768 mono_error_set_type_load_class (error, klass, "%s", msg);
5772 * mono_class_create_from_typedef:
5773 * @image: image where the token is valid
5774 * @type_token: typedef token
5775 * @error: used to return any error found while creating the type
5777 * Create the MonoClass* representing the specified type token.
5778 * @type_token must be a TypeDef token.
5780 * FIXME: don't return NULL on failure, just the the caller figure it out.
5783 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5785 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5786 MonoClass *klass, *parent = NULL;
5787 guint32 cols [MONO_TYPEDEF_SIZE];
5788 guint32 cols_next [MONO_TYPEDEF_SIZE];
5789 guint tidx = mono_metadata_token_index (type_token);
5790 MonoGenericContext *context = NULL;
5791 const char *name, *nspace;
5793 MonoClass **interfaces;
5794 guint32 field_last, method_last;
5795 guint32 nesting_tokeen;
5797 mono_error_init (error);
5799 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5800 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5804 mono_loader_lock ();
5806 if ((klass = (MonoClass *)mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5807 mono_loader_unlock ();
5811 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5813 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5814 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5816 if (mono_metadata_has_generic_params (image, type_token)) {
5817 klass = mono_image_alloc0 (image, sizeof (MonoClassGtd));
5818 klass->class_kind = MONO_CLASS_GTD;
5819 classes_size += sizeof (MonoClassGtd);
5822 klass = mono_image_alloc0 (image, sizeof (MonoClassDef));
5823 klass->class_kind = MONO_CLASS_DEF;
5824 classes_size += sizeof (MonoClassDef);
5829 klass->name_space = nspace;
5831 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5833 klass->image = image;
5834 klass->type_token = type_token;
5835 mono_class_set_flags (klass, cols [MONO_TYPEDEF_FLAGS]);
5837 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
5840 * Check whether we're a generic type definition.
5842 if (mono_class_is_gtd (klass)) {
5843 MonoGenericContainer *generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
5844 generic_container->owner.klass = klass;
5845 generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
5846 context = &generic_container->context;
5847 mono_class_set_generic_container (klass, generic_container);
5848 enable_gclass_recording ();
5851 if (cols [MONO_TYPEDEF_EXTENDS]) {
5853 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5855 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5856 /*WARNING: this must satisfy mono_metadata_type_hash*/
5857 klass->this_arg.byref = 1;
5858 klass->this_arg.data.klass = klass;
5859 klass->this_arg.type = MONO_TYPE_CLASS;
5860 klass->byval_arg.data.klass = klass;
5861 klass->byval_arg.type = MONO_TYPE_CLASS;
5863 parent = mono_class_get_checked (image, parent_token, error);
5864 if (parent && context) /* Always inflate */
5865 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5867 if (parent == NULL) {
5868 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5869 goto parent_failure;
5872 for (tmp = parent; tmp; tmp = tmp->parent) {
5874 mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
5875 goto parent_failure;
5877 if (mono_class_is_gtd (klass) && mono_class_is_ginst (tmp) && mono_class_get_generic_class (tmp)->container_class == klass) {
5878 mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
5879 goto parent_failure;
5884 mono_class_setup_parent (klass, parent);
5886 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5887 mono_class_setup_mono_type (klass);
5889 if (mono_class_is_gtd (klass))
5890 disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
5893 * This might access klass->byval_arg for recursion generated by generic constraints,
5894 * so it has to come after setup_mono_type ().
5896 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5897 klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5898 if (!mono_error_ok (error)) {
5899 /*FIXME implement a mono_class_set_failure_from_mono_error */
5900 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5901 mono_loader_unlock ();
5902 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5907 if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5911 if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5915 klass->cast_class = klass->element_class = klass;
5917 if (!klass->enumtype) {
5918 if (!mono_metadata_interfaces_from_typedef_full (
5919 image, type_token, &interfaces, &icount, FALSE, context, error)){
5921 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5922 mono_loader_unlock ();
5923 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5927 /* This is required now that it is possible for more than 2^16 interfaces to exist. */
5928 g_assert(icount <= 65535);
5930 klass->interfaces = interfaces;
5931 klass->interface_count = icount;
5932 klass->interfaces_inited = 1;
5935 /*g_print ("Load class %s\n", name);*/
5938 * Compute the field and method lists
5940 int first_field_idx = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5941 mono_class_set_first_field_idx (klass, first_field_idx);
5942 int first_method_idx = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5943 mono_class_set_first_method_idx (klass, first_method_idx);
5945 if (tt->rows > tidx){
5946 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5947 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5948 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5950 field_last = image->tables [MONO_TABLE_FIELD].rows;
5951 method_last = image->tables [MONO_TABLE_METHOD].rows;
5954 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5955 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5956 mono_class_set_field_count (klass, field_last - first_field_idx);
5957 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5958 mono_class_set_method_count (klass, method_last - first_method_idx);
5960 /* reserve space to store vector pointer in arrays */
5961 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5962 klass->instance_size += 2 * sizeof (gpointer);
5963 g_assert (mono_class_get_field_count (klass) == 0);
5966 if (klass->enumtype) {
5967 MonoType *enum_basetype = mono_class_find_enum_basetype (klass, error);
5968 if (!enum_basetype) {
5969 /*set it to a default value as the whole runtime can't handle this to be null*/
5970 klass->cast_class = klass->element_class = mono_defaults.int32_class;
5971 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5972 mono_loader_unlock ();
5973 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5976 klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
5980 * If we're a generic type definition, load the constraints.
5981 * We must do this after the class has been constructed to make certain recursive scenarios
5984 if (mono_class_is_gtd (klass) && !mono_metadata_load_generic_param_constraints_checked (image, type_token, mono_class_get_generic_container (klass), error)) {
5985 mono_class_set_type_load_failure (klass, "Could not load generic parameter constrains due to %s", mono_error_get_message (error));
5986 mono_loader_unlock ();
5987 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5991 if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5992 if (!strncmp (name, "Vector", 6))
5993 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");
5994 } else if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "System.Numerics") && !strcmp (nspace, "System.Numerics")) {
5995 if (!strcmp (name, "Vector2") || !strcmp (name, "Vector3") || !strcmp (name, "Vector4"))
5996 klass->simd_type = 1;
5997 } else if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "System.Numerics.Vectors") && !strcmp (nspace, "System.Numerics")) {
5998 if (!strcmp (name, "Vector`1"))
5999 klass->simd_type = 1;
6002 mono_loader_unlock ();
6004 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6009 mono_class_setup_mono_type (klass);
6010 mono_loader_unlock ();
6011 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
6015 /** Is klass a Nullable<T> ginst? */
6017 mono_class_is_nullable (MonoClass *klass)
6019 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
6020 return gklass && gklass->container_class == mono_defaults.generic_nullable_class;
6024 /** if klass is T? return T */
6026 mono_class_get_nullable_param (MonoClass *klass)
6028 g_assert (mono_class_is_nullable (klass));
6029 return mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
6033 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
6037 MonoGenericClass *gclass = mono_class_get_generic_class (klass);
6039 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
6040 if (!mono_error_ok (&error)) {
6041 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
6042 klass->parent = mono_defaults.object_class;
6043 mono_class_set_type_load_failure (klass, "Parent is a generic type instantiation that failed due to: %s", mono_error_get_message (&error));
6044 mono_error_cleanup (&error);
6048 mono_class_setup_parent (klass, klass->parent);
6050 if (klass->enumtype) {
6051 klass->cast_class = gtd->cast_class;
6052 klass->element_class = gtd->element_class;
6058 * Create the `MonoClass' for an instantiation of a generic type.
6059 * We only do this if we actually need it.
6062 mono_generic_class_get_class (MonoGenericClass *gclass)
6064 MonoClass *klass, *gklass;
6066 if (gclass->cached_class)
6067 return gclass->cached_class;
6069 mono_loader_lock ();
6070 if (gclass->cached_class) {
6071 mono_loader_unlock ();
6072 return gclass->cached_class;
6075 klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClassGenericInst));
6077 gklass = gclass->container_class;
6079 if (record_gclass_instantiation > 0)
6080 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
6082 if (gklass->nested_in) {
6083 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
6084 klass->nested_in = gklass->nested_in;
6087 klass->name = gklass->name;
6088 klass->name_space = gklass->name_space;
6090 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6092 klass->image = gklass->image;
6093 klass->type_token = gklass->type_token;
6095 klass->class_kind = MONO_CLASS_GINST;
6097 ((MonoClassGenericInst*)klass)->generic_class = gclass;
6099 klass->byval_arg.type = MONO_TYPE_GENERICINST;
6100 klass->this_arg.type = klass->byval_arg.type;
6101 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
6102 klass->this_arg.byref = TRUE;
6103 klass->enumtype = gklass->enumtype;
6104 klass->valuetype = gklass->valuetype;
6105 klass->simd_type = gklass->simd_type;
6107 klass->cast_class = klass->element_class = klass;
6109 if (mono_class_is_nullable (klass))
6110 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
6113 * We're not interested in the nested classes of a generic instance.
6114 * We use the generic type definition to look for nested classes.
6117 mono_generic_class_setup_parent (klass, gklass);
6119 if (gclass->is_dynamic) {
6121 * 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.
6122 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
6123 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
6125 if (!gklass->wastypebuilder)
6128 mono_class_setup_supertypes (klass);
6130 if (klass->enumtype) {
6132 * For enums, gklass->fields might not been set, but instance_size etc. is
6133 * already set in mono_reflection_create_internal_class (). For non-enums,
6134 * these will be computed normally in mono_class_layout_fields ().
6136 klass->instance_size = gklass->instance_size;
6137 klass->sizes.class_size = gklass->sizes.class_size;
6138 mono_memory_barrier ();
6139 klass->size_inited = 1;
6143 mono_memory_barrier ();
6144 gclass->cached_class = klass;
6146 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6148 ++class_ginst_count;
6149 inflated_classes_size += sizeof (MonoClassGenericInst);
6151 mono_loader_unlock ();
6157 get_image_for_container (MonoGenericContainer *container)
6160 if (container->is_anonymous) {
6161 result = container->owner.image;
6164 if (container->is_method) {
6165 MonoMethod *method = container->owner.method;
6166 g_assert_checked (method);
6167 klass = method->klass;
6169 klass = container->owner.klass;
6171 g_assert_checked (klass);
6172 result = klass->image;
6179 get_image_for_generic_param (MonoGenericParam *param)
6181 MonoGenericContainer *container = mono_generic_param_owner (param);
6182 g_assert_checked (container);
6183 return get_image_for_container (container);
6186 // Make a string in the designated image consisting of a single integer.
6187 #define INT_STRING_SIZE 16
6189 make_generic_name_string (MonoImage *image, int num)
6191 char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
6192 g_snprintf (name, INT_STRING_SIZE, "%d", num);
6196 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
6197 // pinfo is derived from param by the caller for us.
6199 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
6201 MonoClass *klass, **ptr;
6203 MonoGenericContainer *container = mono_generic_param_owner (param);
6204 g_assert_checked (container);
6206 MonoImage *image = get_image_for_container (container);
6207 gboolean is_mvar = container->is_method;
6208 gboolean is_anonymous = container->is_anonymous;
6210 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassGenericParam));
6211 klass->class_kind = MONO_CLASS_GPARAM;
6212 classes_size += sizeof (MonoClassGenericParam);
6213 ++class_gparam_count;
6216 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
6218 int n = mono_generic_param_num (param);
6219 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
6223 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , "" );
6224 } else if (is_mvar) {
6225 MonoMethod *omethod = container->owner.method;
6226 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
6228 MonoClass *oklass = container->owner.klass;
6229 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
6232 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6234 // Count non-NULL items in pinfo->constraints
6237 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6241 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6242 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
6244 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
6245 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
6247 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
6250 if (count - pos > 0) {
6251 klass->interface_count = count - pos;
6252 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
6253 klass->interfaces_inited = TRUE;
6254 for (i = pos; i < count; i++)
6255 CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
6258 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
6260 klass->inited = TRUE;
6261 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class , klass );
6262 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
6264 klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6265 klass->this_arg.type = klass->byval_arg.type;
6266 CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param , param );
6267 CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
6268 klass->this_arg.byref = TRUE;
6270 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6271 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6273 /*Init these fields to sane values*/
6274 klass->min_align = 1;
6276 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6277 * constrained to, the JIT depends on this.
6279 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6280 mono_memory_barrier ();
6281 klass->size_inited = 1;
6283 mono_class_setup_supertypes (klass);
6285 if (count - pos > 0) {
6286 mono_class_setup_vtable (klass->parent);
6287 if (mono_class_has_failure (klass->parent))
6288 mono_class_set_type_load_failure (klass, "Failed to setup parent interfaces");
6290 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6296 #define FAST_CACHE_SIZE 16
6299 * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6300 * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6301 * we cache the MonoClasses.
6302 * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6303 * LOCKING: Takes the image lock depending on @take_lock.
6306 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6308 int n = mono_generic_param_num (param);
6309 MonoImage *image = get_image_for_generic_param (param);
6310 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6311 MonoClass *klass = NULL;
6316 // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6317 // For high numbers or constraints we have to use pointer hashes.
6318 if (param->gshared_constraint) {
6319 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6322 mono_image_lock (image);
6323 klass = (MonoClass *)g_hash_table_lookup (ht, param);
6325 mono_image_unlock (image);
6330 if (n < FAST_CACHE_SIZE) {
6332 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6334 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6336 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6339 mono_image_lock (image);
6340 klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6342 mono_image_unlock (image);
6349 * LOCKING: Image lock (param->image) must be held
6352 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6354 int n = mono_generic_param_num (param);
6355 MonoImage *image = get_image_for_generic_param (param);
6356 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6360 if (param->gshared_constraint) {
6361 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6363 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6364 mono_memory_barrier ();
6366 image->mvar_cache_constrained = ht;
6368 image->var_cache_constrained = ht;
6370 g_hash_table_insert (ht, param, klass);
6371 } else if (n < FAST_CACHE_SIZE) {
6373 /* Requires locking to avoid droping an already published class */
6374 if (!image->mvar_cache_fast)
6375 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6376 image->mvar_cache_fast [n] = klass;
6378 if (!image->var_cache_fast)
6379 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6380 image->var_cache_fast [n] = klass;
6383 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6385 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6387 ht = g_hash_table_new (NULL, NULL);
6388 mono_memory_barrier ();
6390 image->mvar_cache_slow = ht;
6392 image->var_cache_slow = ht;
6395 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6400 * LOCKING: Acquires the image lock (@image).
6403 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6405 MonoImage *image = get_image_for_generic_param (param);
6406 MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6407 MonoClass *klass, *klass2;
6409 // If a klass already exists for this object and is cached, return it.
6410 if (pinfo) // Non-anonymous
6411 klass = pinfo->pklass;
6413 klass = get_anon_gparam_class (param, TRUE);
6418 // Create a new klass
6419 klass = make_generic_param_class (param, pinfo);
6421 // Now we need to cache the klass we created.
6422 // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6423 // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6424 // and allow our newly-created klass object to just leak.
6425 mono_memory_barrier ();
6427 mono_image_lock (image);
6429 // Here "klass2" refers to the klass potentially created by the other thread.
6430 if (pinfo) // Repeat check from above
6431 klass2 = pinfo->pklass;
6433 klass2 = get_anon_gparam_class (param, FALSE);
6440 pinfo->pklass = klass;
6442 set_anon_gparam_class (param, klass);
6444 mono_image_unlock (image);
6446 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6448 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED); // Alert profiler about botched class create
6450 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6456 * mono_class_from_generic_parameter:
6457 * @param: Parameter to find/construct a class for.
6458 * @arg2: Is ignored.
6459 * @arg3: Is ignored.
6462 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6464 return mono_class_from_generic_parameter_internal (param);
6469 mono_ptr_class_get (MonoType *type)
6472 MonoClass *el_class;
6476 el_class = mono_class_from_mono_type (type);
6477 image = el_class->image;
6479 mono_image_lock (image);
6480 if (image->ptr_cache) {
6481 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6482 mono_image_unlock (image);
6486 mono_image_unlock (image);
6488 result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassPointer));
6490 classes_size += sizeof (MonoClassPointer);
6491 ++class_pointer_count;
6493 result->parent = NULL; /* no parent for PTR types */
6494 result->name_space = el_class->name_space;
6495 name = g_strdup_printf ("%s*", el_class->name);
6496 result->name = mono_image_strdup (image, name);
6497 result->class_kind = MONO_CLASS_POINTER;
6500 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6502 result->image = el_class->image;
6503 result->inited = TRUE;
6504 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6505 result->cast_class = result->element_class = el_class;
6506 result->blittable = TRUE;
6508 result->byval_arg.type = MONO_TYPE_PTR;
6509 result->this_arg.type = result->byval_arg.type;
6510 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6511 result->this_arg.byref = TRUE;
6513 mono_class_setup_supertypes (result);
6515 mono_image_lock (image);
6516 if (image->ptr_cache) {
6518 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6519 mono_image_unlock (image);
6520 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6524 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6526 g_hash_table_insert (image->ptr_cache, el_class, result);
6527 mono_image_unlock (image);
6529 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6535 mono_fnptr_class_get (MonoMethodSignature *sig)
6538 static GHashTable *ptr_hash = NULL;
6540 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6542 mono_loader_lock ();
6545 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6547 if ((result = (MonoClass *)g_hash_table_lookup (ptr_hash, sig))) {
6548 mono_loader_unlock ();
6551 result = g_new0 (MonoClass, 1);
6553 classes_size += sizeof (MonoClassPointer);
6554 ++class_pointer_count;
6556 result->parent = NULL; /* no parent for PTR types */
6557 result->name_space = "System";
6558 result->name = "MonoFNPtrFakeClass";
6559 result->class_kind = MONO_CLASS_POINTER;
6561 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6563 result->image = mono_defaults.corlib; /* need to fix... */
6564 result->inited = TRUE;
6565 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6566 result->cast_class = result->element_class = result;
6567 result->blittable = TRUE;
6569 result->byval_arg.type = MONO_TYPE_FNPTR;
6570 result->this_arg.type = result->byval_arg.type;
6571 result->this_arg.data.method = result->byval_arg.data.method = sig;
6572 result->this_arg.byref = TRUE;
6573 result->blittable = TRUE;
6575 mono_class_setup_supertypes (result);
6577 g_hash_table_insert (ptr_hash, sig, result);
6579 mono_loader_unlock ();
6581 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6587 * mono_class_from_mono_type:
6588 * @type: describes the type to return
6590 * This returns a MonoClass for the specified MonoType, the value is never NULL.
6593 mono_class_from_mono_type (MonoType *type)
6595 switch (type->type) {
6596 case MONO_TYPE_OBJECT:
6597 return type->data.klass? type->data.klass: mono_defaults.object_class;
6598 case MONO_TYPE_VOID:
6599 return type->data.klass? type->data.klass: mono_defaults.void_class;
6600 case MONO_TYPE_BOOLEAN:
6601 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6602 case MONO_TYPE_CHAR:
6603 return type->data.klass? type->data.klass: mono_defaults.char_class;
6605 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6607 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6609 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6611 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6613 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6615 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6617 return type->data.klass? type->data.klass: mono_defaults.int_class;
6619 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6621 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6623 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6625 return type->data.klass? type->data.klass: mono_defaults.single_class;
6627 return type->data.klass? type->data.klass: mono_defaults.double_class;
6628 case MONO_TYPE_STRING:
6629 return type->data.klass? type->data.klass: mono_defaults.string_class;
6630 case MONO_TYPE_TYPEDBYREF:
6631 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6632 case MONO_TYPE_ARRAY:
6633 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6635 return mono_ptr_class_get (type->data.type);
6636 case MONO_TYPE_FNPTR:
6637 return mono_fnptr_class_get (type->data.method);
6638 case MONO_TYPE_SZARRAY:
6639 return mono_array_class_get (type->data.klass, 1);
6640 case MONO_TYPE_CLASS:
6641 case MONO_TYPE_VALUETYPE:
6642 return type->data.klass;
6643 case MONO_TYPE_GENERICINST:
6644 return mono_generic_class_get_class (type->data.generic_class);
6645 case MONO_TYPE_MVAR:
6647 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6649 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6650 g_assert_not_reached ();
6653 // Yes, this returns NULL, even if it is documented as not doing so, but there
6654 // is no way for the code to make it this far, due to the assert above.
6659 * mono_type_retrieve_from_typespec
6660 * @image: context where the image is created
6661 * @type_spec: typespec token
6662 * @context: the generic context used to evaluate generic instantiations in
6665 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6667 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6669 *did_inflate = FALSE;
6674 if (context && (context->class_inst || context->method_inst)) {
6675 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6677 if (!mono_error_ok (error)) {
6683 *did_inflate = TRUE;
6690 * mono_class_create_from_typespec
6691 * @image: context where the image is created
6692 * @type_spec: typespec token
6693 * @context: the generic context used to evaluate generic instantiations in
6696 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6699 gboolean inflated = FALSE;
6700 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6701 return_val_if_nok (error, NULL);
6702 ret = mono_class_from_mono_type (t);
6704 mono_metadata_free_type (t);
6709 * mono_bounded_array_class_get:
6710 * @element_class: element class
6711 * @rank: the dimension of the array class
6712 * @bounded: whenever the array has non-zero bounds
6714 * Returns: A class object describing the array with element type @element_type and
6718 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6722 MonoClass *parent = NULL;
6723 GSList *list, *rootlist = NULL;
6727 g_assert (rank <= 255);
6730 /* bounded only matters for one-dimensional arrays */
6733 image = eclass->image;
6735 if (rank == 1 && !bounded) {
6737 * This case is very frequent not just during compilation because of calls
6738 * from mono_class_from_mono_type (), mono_array_new (),
6739 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6741 mono_os_mutex_lock (&image->szarray_cache_lock);
6742 if (!image->szarray_cache)
6743 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6744 klass = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6745 mono_os_mutex_unlock (&image->szarray_cache_lock);
6749 mono_loader_lock ();
6751 mono_loader_lock ();
6753 if (!image->array_cache)
6754 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6756 if ((rootlist = list = (GSList *)g_hash_table_lookup (image->array_cache, eclass))) {
6757 for (; list; list = list->next) {
6758 klass = (MonoClass *)list->data;
6759 if ((klass->rank == rank) && (klass->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6760 mono_loader_unlock ();
6767 parent = mono_defaults.array_class;
6768 if (!parent->inited)
6769 mono_class_init (parent);
6771 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassArray));
6773 klass->image = image;
6774 klass->name_space = eclass->name_space;
6775 klass->class_kind = MONO_CLASS_ARRAY;
6777 nsize = strlen (eclass->name);
6778 name = (char *)g_malloc (nsize + 2 + rank + 1);
6779 memcpy (name, eclass->name, nsize);
6782 memset (name + nsize + 1, ',', rank - 1);
6784 name [nsize + rank] = '*';
6785 name [nsize + rank + bounded] = ']';
6786 name [nsize + rank + bounded + 1] = 0;
6787 klass->name = mono_image_strdup (image, name);
6790 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6792 classes_size += sizeof (MonoClassArray);
6793 ++class_array_count;
6795 klass->type_token = 0;
6796 klass->parent = parent;
6797 klass->instance_size = mono_class_instance_size (klass->parent);
6799 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6800 /*Arrays of those two types are invalid.*/
6801 MonoError prepared_error;
6802 mono_error_init (&prepared_error);
6803 mono_error_set_invalid_program (&prepared_error, "Arrays of void or System.TypedReference types are invalid.");
6804 mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6805 mono_error_cleanup (&prepared_error);
6806 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6807 guint32 ref_info_handle = mono_class_get_ref_info_handle (eclass);
6808 if (!ref_info_handle || eclass->wastypebuilder) {
6809 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6810 g_assert (ref_info_handle && !eclass->wastypebuilder);
6812 /* element_size -1 is ok as this is not an instantitable type*/
6813 klass->sizes.element_size = -1;
6815 klass->sizes.element_size = mono_class_array_element_size (eclass);
6817 mono_class_setup_supertypes (klass);
6819 if (mono_class_is_ginst (eclass))
6820 mono_class_init (eclass);
6821 if (!eclass->size_inited)
6822 mono_class_setup_fields (eclass);
6823 mono_class_set_type_load_failure_causedby_class (klass, eclass, "Could not load array element type");
6824 /*FIXME we fail the array type, but we have to let other fields be set.*/
6826 klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6830 if (eclass->enumtype)
6831 klass->cast_class = eclass->element_class;
6833 klass->cast_class = eclass;
6835 switch (klass->cast_class->byval_arg.type) {
6837 klass->cast_class = mono_defaults.byte_class;
6840 klass->cast_class = mono_defaults.int16_class;
6843 #if SIZEOF_VOID_P == 4
6847 klass->cast_class = mono_defaults.int32_class;
6850 #if SIZEOF_VOID_P == 8
6854 klass->cast_class = mono_defaults.int64_class;
6860 klass->element_class = eclass;
6862 if ((rank > 1) || bounded) {
6863 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6864 klass->byval_arg.type = MONO_TYPE_ARRAY;
6865 klass->byval_arg.data.array = at;
6866 at->eklass = eclass;
6868 /* FIXME: complete.... */
6870 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6871 klass->byval_arg.data.klass = eclass;
6873 klass->this_arg = klass->byval_arg;
6874 klass->this_arg.byref = 1;
6876 //WTF was this? it's wrong
6877 // klass->generic_container = eclass->generic_container;
6879 if (rank == 1 && !bounded) {
6880 MonoClass *prev_class;
6882 mono_os_mutex_lock (&image->szarray_cache_lock);
6883 prev_class = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6885 /* Someone got in before us */
6888 g_hash_table_insert (image->szarray_cache, eclass, klass);
6889 mono_os_mutex_unlock (&image->szarray_cache_lock);
6891 list = g_slist_append (rootlist, klass);
6892 g_hash_table_insert (image->array_cache, eclass, list);
6895 mono_loader_unlock ();
6897 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6903 * mono_array_class_get:
6904 * @element_class: element class
6905 * @rank: the dimension of the array class
6907 * Returns: A class object describing the array with element type @element_type and
6911 mono_array_class_get (MonoClass *eclass, guint32 rank)
6913 return mono_bounded_array_class_get (eclass, rank, FALSE);
6917 * mono_class_instance_size:
6920 * Use to get the size of a class in bytes.
6922 * Returns: The size of an object instance
6925 mono_class_instance_size (MonoClass *klass)
6927 if (!klass->size_inited)
6928 mono_class_init (klass);
6930 return klass->instance_size;
6934 * mono_class_min_align:
6937 * Use to get the computed minimum alignment requirements for the specified class.
6939 * Returns: minimum alignment requirements
6942 mono_class_min_align (MonoClass *klass)
6944 if (!klass->size_inited)
6945 mono_class_init (klass);
6947 return klass->min_align;
6951 * mono_class_value_size:
6954 * This function is used for value types, and return the
6955 * space and the alignment to store that kind of value object.
6957 * Returns: the size of a value of kind @klass
6960 mono_class_value_size (MonoClass *klass, guint32 *align)
6964 /* fixme: check disable, because we still have external revereces to
6965 * mscorlib and Dummy Objects
6967 /*g_assert (klass->valuetype);*/
6969 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6972 *align = klass->min_align;
6978 * mono_class_data_size:
6981 * Returns: The size of the static class data
6984 mono_class_data_size (MonoClass *klass)
6987 mono_class_init (klass);
6988 /* This can happen with dynamically created types */
6989 if (!klass->fields_inited)
6990 mono_class_setup_fields (klass);
6992 /* in arrays, sizes.class_size is unioned with element_size
6993 * and arrays have no static fields
6997 return klass->sizes.class_size;
7001 * Auxiliary routine to mono_class_get_field
7003 * Takes a field index instead of a field token.
7005 static MonoClassField *
7006 mono_class_get_field_idx (MonoClass *klass, int idx)
7008 mono_class_setup_fields (klass);
7009 if (mono_class_has_failure (klass))
7013 int first_field_idx = mono_class_get_first_field_idx (klass);
7014 int fcount = mono_class_get_field_count (klass);
7015 if (klass->image->uncompressed_metadata) {
7017 * first_field_idx points to the FieldPtr table, while idx points into the
7018 * Field table, so we have to do a search.
7020 /*FIXME this is broken for types with multiple fields with the same name.*/
7021 const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
7024 for (i = 0; i < fcount; ++i)
7025 if (mono_field_get_name (&klass->fields [i]) == name)
7026 return &klass->fields [i];
7027 g_assert_not_reached ();
7030 if ((idx >= first_field_idx) && (idx < first_field_idx + fcount)){
7031 return &klass->fields [idx - first_field_idx];
7035 klass = klass->parent;
7041 * mono_class_get_field:
7042 * @class: the class to lookup the field.
7043 * @field_token: the field token
7045 * Returns: A MonoClassField representing the type and offset of
7046 * the field, or a NULL value if the field does not belong to this
7050 mono_class_get_field (MonoClass *klass, guint32 field_token)
7052 int idx = mono_metadata_token_index (field_token);
7054 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
7056 return mono_class_get_field_idx (klass, idx - 1);
7060 * mono_class_get_field_from_name:
7061 * @klass: the class to lookup the field.
7062 * @name: the field name
7064 * Search the class @klass and it's parents for a field with the name @name.
7066 * Returns: The MonoClassField pointer of the named field or NULL
7069 mono_class_get_field_from_name (MonoClass *klass, const char *name)
7071 return mono_class_get_field_from_name_full (klass, name, NULL);
7075 * mono_class_get_field_from_name_full:
7076 * @klass: the class to lookup the field.
7077 * @name: the field name
7078 * @type: the type of the fields. This optional.
7080 * Search the class @klass and it's parents for a field with the name @name and type @type.
7082 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
7083 * of its generic type definition.
7085 * Returns: The MonoClassField pointer of the named field or NULL
7088 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
7092 mono_class_setup_fields (klass);
7093 if (mono_class_has_failure (klass))
7097 int fcount = mono_class_get_field_count (klass);
7098 for (i = 0; i < fcount; ++i) {
7099 MonoClassField *field = &klass->fields [i];
7101 if (strcmp (name, mono_field_get_name (field)) != 0)
7105 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
7106 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
7111 klass = klass->parent;
7117 * mono_class_get_field_token:
7118 * @field: the field we need the token of
7120 * Get the token of a field. Note that the tokesn is only valid for the image
7121 * the field was loaded from. Don't use this function for fields in dynamic types.
7123 * Returns: The token representing the field in the image it was loaded from.
7126 mono_class_get_field_token (MonoClassField *field)
7128 MonoClass *klass = field->parent;
7131 mono_class_setup_fields (klass);
7136 int first_field_idx = mono_class_get_first_field_idx (klass);
7137 int fcount = mono_class_get_field_count (klass);
7138 for (i = 0; i < fcount; ++i) {
7139 if (&klass->fields [i] == field) {
7140 int idx = first_field_idx + i + 1;
7142 if (klass->image->uncompressed_metadata)
7143 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
7144 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
7147 klass = klass->parent;
7150 g_assert_not_reached ();
7155 mono_field_get_index (MonoClassField *field)
7157 int index = field - field->parent->fields;
7158 g_assert (index >= 0 && index < mono_class_get_field_count (field->parent));
7164 * mono_class_get_field_default_value:
7166 * Return the default value of the field as a pointer into the metadata blob.
7169 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
7172 guint32 constant_cols [MONO_CONSTANT_SIZE];
7174 MonoClass *klass = field->parent;
7176 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7178 MonoClassExt *ext = mono_class_get_ext (klass);
7179 if (!ext || !ext->field_def_values) {
7180 MonoFieldDefaultValue *def_values;
7182 mono_class_alloc_ext (klass);
7183 ext = mono_class_get_ext (klass);
7185 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
7187 mono_image_lock (klass->image);
7188 mono_memory_barrier ();
7189 if (!ext->field_def_values)
7190 ext->field_def_values = def_values;
7191 mono_image_unlock (klass->image);
7194 field_index = mono_field_get_index (field);
7196 if (!ext->field_def_values [field_index].data) {
7197 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7201 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7203 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7204 ext->field_def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7205 ext->field_def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7208 *def_type = ext->field_def_values [field_index].def_type;
7209 return ext->field_def_values [field_index].data;
7213 mono_property_get_index (MonoProperty *prop)
7215 MonoClassExt *ext = mono_class_get_ext (prop->parent);
7216 int index = prop - ext->properties;
7218 g_assert (index >= 0 && index < ext->property.count);
7224 * mono_class_get_property_default_value:
7226 * Return the default value of the field as a pointer into the metadata blob.
7229 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7232 guint32 constant_cols [MONO_CONSTANT_SIZE];
7233 MonoClass *klass = property->parent;
7235 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7237 * We don't cache here because it is not used by C# so it's quite rare, but
7238 * we still do the lookup in klass->ext because that is where the data
7239 * is stored for dynamic assemblies.
7242 if (image_is_dynamic (klass->image)) {
7243 MonoClassExt *ext = mono_class_get_ext (klass);
7244 int prop_index = mono_property_get_index (property);
7245 if (ext->prop_def_values && ext->prop_def_values [prop_index].data) {
7246 *def_type = ext->prop_def_values [prop_index].def_type;
7247 return ext->prop_def_values [prop_index].data;
7251 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7255 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7256 *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7257 return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7261 mono_class_get_event_token (MonoEvent *event)
7263 MonoClass *klass = event->parent;
7267 MonoClassExt *ext = mono_class_get_ext (klass);
7269 for (i = 0; i < ext->event.count; ++i) {
7270 if (&ext->events [i] == event)
7271 return mono_metadata_make_token (MONO_TABLE_EVENT, ext->event.first + i + 1);
7274 klass = klass->parent;
7277 g_assert_not_reached ();
7282 * mono_class_get_property_from_name:
7284 * @name: name of the property to lookup in the specified class
7286 * Use this method to lookup a property in a class
7287 * Returns: the MonoProperty with the given name, or NULL if the property
7288 * does not exist on the @klass.
7291 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7295 gpointer iter = NULL;
7296 while ((p = mono_class_get_properties (klass, &iter))) {
7297 if (! strcmp (name, p->name))
7300 klass = klass->parent;
7306 * mono_class_get_property_token:
7307 * @prop: MonoProperty to query
7309 * Returns: The ECMA token for the specified property.
7312 mono_class_get_property_token (MonoProperty *prop)
7314 MonoClass *klass = prop->parent;
7318 gpointer iter = NULL;
7319 MonoClassExt *ext = mono_class_get_ext (klass);
7320 while ((p = mono_class_get_properties (klass, &iter))) {
7321 if (&ext->properties [i] == prop)
7322 return mono_metadata_make_token (MONO_TABLE_PROPERTY, ext->property.first + i + 1);
7326 klass = klass->parent;
7329 g_assert_not_reached ();
7334 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7336 const char *name, *nspace;
7337 if (image_is_dynamic (image))
7338 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7340 switch (type_token & 0xff000000){
7341 case MONO_TOKEN_TYPE_DEF: {
7342 guint32 cols [MONO_TYPEDEF_SIZE];
7343 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7344 guint tidx = mono_metadata_token_index (type_token);
7346 if (tidx > tt->rows)
7347 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7349 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7350 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7351 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7352 if (strlen (nspace) == 0)
7353 return g_strdup_printf ("%s", name);
7355 return g_strdup_printf ("%s.%s", nspace, name);
7358 case MONO_TOKEN_TYPE_REF: {
7360 guint32 cols [MONO_TYPEREF_SIZE];
7361 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7362 guint tidx = mono_metadata_token_index (type_token);
7365 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7367 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7368 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7369 mono_error_cleanup (&error);
7373 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7374 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7375 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7376 if (strlen (nspace) == 0)
7377 return g_strdup_printf ("%s", name);
7379 return g_strdup_printf ("%s.%s", nspace, name);
7382 case MONO_TOKEN_TYPE_SPEC:
7383 return g_strdup_printf ("Typespec 0x%08x", type_token);
7385 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7390 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7392 if (image_is_dynamic (image))
7393 return g_strdup_printf ("DynamicAssembly %s", image->name);
7395 switch (type_token & 0xff000000){
7396 case MONO_TOKEN_TYPE_DEF:
7397 if (image->assembly)
7398 return mono_stringify_assembly_name (&image->assembly->aname);
7399 else if (image->assembly_name)
7400 return g_strdup (image->assembly_name);
7401 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7402 case MONO_TOKEN_TYPE_REF: {
7404 MonoAssemblyName aname;
7405 guint32 cols [MONO_TYPEREF_SIZE];
7406 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7407 guint32 idx = mono_metadata_token_index (type_token);
7410 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7412 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7413 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7414 mono_error_cleanup (&error);
7417 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7419 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7420 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7421 case MONO_RESOLUTION_SCOPE_MODULE:
7423 return g_strdup ("");
7424 case MONO_RESOLUTION_SCOPE_MODULEREF:
7426 return g_strdup ("");
7427 case MONO_RESOLUTION_SCOPE_TYPEREF:
7429 return g_strdup ("");
7430 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7431 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7432 return mono_stringify_assembly_name (&aname);
7434 g_assert_not_reached ();
7438 case MONO_TOKEN_TYPE_SPEC:
7440 return g_strdup ("");
7442 g_assert_not_reached ();
7449 * mono_class_get_full:
7450 * @image: the image where the class resides
7451 * @type_token: the token for the class
7452 * @context: the generic context used to evaluate generic instantiations in
7453 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7455 * Returns: The MonoClass that represents @type_token in @image
7458 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7462 klass = mono_class_get_checked (image, type_token, &error);
7464 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7465 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7467 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7473 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7477 mono_error_init (error);
7478 klass = mono_class_get_checked (image, type_token, error);
7480 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7481 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7486 * mono_class_get_checked:
7487 * @image: the image where the class resides
7488 * @type_token: the token for the class
7489 * @error: error object to return any error
7491 * Returns: The MonoClass that represents @type_token in @image, or NULL on error.
7494 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7496 MonoClass *klass = NULL;
7498 mono_error_init (error);
7500 if (image_is_dynamic (image)) {
7501 int table = mono_metadata_token_table (type_token);
7503 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7504 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7507 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
7511 switch (type_token & 0xff000000){
7512 case MONO_TOKEN_TYPE_DEF:
7513 klass = mono_class_create_from_typedef (image, type_token, error);
7515 case MONO_TOKEN_TYPE_REF:
7516 klass = mono_class_from_typeref_checked (image, type_token, error);
7518 case MONO_TOKEN_TYPE_SPEC:
7519 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7522 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7526 /* Generic case, should be avoided for when a better error is possible. */
7527 if (!klass && mono_error_ok (error)) {
7528 char *name = mono_class_name_from_token (image, type_token);
7529 char *assembly = mono_assembly_name_from_token (image, type_token);
7530 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7538 * mono_type_get_checked:
7539 * @image: the image where the type resides
7540 * @type_token: the token for the type
7541 * @context: the generic context used to evaluate generic instantiations in
7542 * @error: Error handling context
7544 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7546 * Returns: The MonoType that represents @type_token in @image
7549 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7551 MonoType *type = NULL;
7552 gboolean inflated = FALSE;
7554 mono_error_init (error);
7556 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7557 if (image_is_dynamic (image)) {
7558 MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
7559 return_val_if_nok (error, NULL);
7560 return mono_class_get_type (klass);
7563 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7564 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7571 return mono_class_get_type (klass);
7574 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7581 MonoType *tmp = type;
7582 type = mono_class_get_type (mono_class_from_mono_type (type));
7583 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7584 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7585 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7587 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7589 if (type->type != tmp->type)
7592 mono_metadata_free_type (tmp);
7599 * @image: image where the class token will be looked up.
7600 * @type_token: a type token from the image
7602 * Returns the MonoClass with the given @type_token on the @image
7605 mono_class_get (MonoImage *image, guint32 type_token)
7607 return mono_class_get_full (image, type_token, NULL);
7611 * mono_image_init_name_cache:
7613 * Initializes the class name cache stored in image->name_cache.
7615 * LOCKING: Acquires the corresponding image lock.
7618 mono_image_init_name_cache (MonoImage *image)
7620 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7621 guint32 cols [MONO_TYPEDEF_SIZE];
7624 guint32 i, visib, nspace_index;
7625 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7627 if (image->name_cache)
7630 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7632 if (image_is_dynamic (image)) {
7633 mono_image_lock (image);
7634 if (image->name_cache) {
7635 /* Somebody initialized it before us */
7636 g_hash_table_destroy (the_name_cache);
7638 mono_atomic_store_release (&image->name_cache, the_name_cache);
7640 mono_image_unlock (image);
7644 /* Temporary hash table to avoid lookups in the nspace_table */
7645 name_cache2 = g_hash_table_new (NULL, NULL);
7647 for (i = 1; i <= t->rows; ++i) {
7648 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7649 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7651 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7652 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7654 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7656 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7657 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7659 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7660 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7661 if (!nspace_table) {
7662 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7663 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7664 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7667 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7670 /* Load type names from EXPORTEDTYPES table */
7672 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7673 guint32 cols [MONO_EXP_TYPE_SIZE];
7676 for (i = 0; i < t->rows; ++i) {
7677 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7679 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7680 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7684 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7685 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7687 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7688 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7689 if (!nspace_table) {
7690 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7691 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7692 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7695 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7699 g_hash_table_destroy (name_cache2);
7701 mono_image_lock (image);
7702 if (image->name_cache) {
7703 /* Somebody initialized it before us */
7704 g_hash_table_destroy (the_name_cache);
7706 mono_atomic_store_release (&image->name_cache, the_name_cache);
7708 mono_image_unlock (image);
7711 /*FIXME Only dynamic assemblies should allow this operation.*/
7713 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7714 const char *name, guint32 index)
7716 GHashTable *nspace_table;
7717 GHashTable *name_cache;
7720 mono_image_init_name_cache (image);
7721 mono_image_lock (image);
7723 name_cache = image->name_cache;
7724 if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7725 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7726 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7729 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7730 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7732 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7734 mono_image_unlock (image);
7743 find_nocase (gpointer key, gpointer value, gpointer user_data)
7745 char *name = (char*)key;
7746 FindUserData *data = (FindUserData*)user_data;
7748 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7749 data->value = value;
7753 * mono_class_from_name_case:
7754 * @image: The MonoImage where the type is looked up in
7755 * @name_space: the type namespace
7756 * @name: the type short name.
7757 * @deprecated: use the mono_class_from_name_case_checked variant instead.
7759 * Obtains a MonoClass with a given namespace and a given name which
7760 * is located in the given MonoImage. The namespace and name
7761 * lookups are case insensitive.
7764 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7767 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7768 mono_error_cleanup (&error);
7774 * mono_class_from_name_case:
7775 * @image: The MonoImage where the type is looked up in
7776 * @name_space: the type namespace
7777 * @name: the type short name.
7780 * Obtains a MonoClass with a given namespace and a given name which
7781 * is located in the given MonoImage. The namespace and name
7782 * lookups are case insensitive.
7784 * Returns: The MonoClass if the given namespace and name were found, or NULL if it
7785 * was not found. The @error object will contain information about the problem
7789 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7791 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7792 guint32 cols [MONO_TYPEDEF_SIZE];
7797 mono_error_init (error);
7799 if (image_is_dynamic (image)) {
7801 FindUserData user_data;
7803 mono_image_init_name_cache (image);
7804 mono_image_lock (image);
7806 user_data.key = name_space;
7807 user_data.value = NULL;
7808 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7810 if (user_data.value) {
7811 GHashTable *nspace_table = (GHashTable*)user_data.value;
7813 user_data.key = name;
7814 user_data.value = NULL;
7816 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7818 if (user_data.value)
7819 token = GPOINTER_TO_UINT (user_data.value);
7822 mono_image_unlock (image);
7825 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7831 /* add a cache if needed */
7832 for (i = 1; i <= t->rows; ++i) {
7833 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7834 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7836 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7837 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7839 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7841 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7842 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7843 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7844 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7850 return_nested_in (MonoClass *klass, char *nested)
7853 char *s = strchr (nested, '/');
7854 gpointer iter = NULL;
7861 while ((found = mono_class_get_nested_types (klass, &iter))) {
7862 if (strcmp (found->name, nested) == 0) {
7864 return return_nested_in (found, s);
7872 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7874 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7875 MonoImage *file_image;
7879 mono_error_init (error);
7882 * The EXPORTEDTYPES table only contains public types, so have to search the
7884 * Note: image->modules contains the contents of the MODULEREF table, while
7885 * the real module list is in the FILE table.
7887 for (i = 0; i < file_table->rows; i++) {
7888 guint32 cols [MONO_FILE_SIZE];
7889 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7890 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7893 file_image = mono_image_load_file_for_image_checked (image, i + 1, error);
7895 klass = mono_class_from_name_checked (file_image, name_space, name, error);
7896 if (klass || !is_ok (error))
7905 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7907 GHashTable *nspace_table;
7908 MonoImage *loaded_image;
7915 mono_error_init (error);
7917 // Checking visited images avoids stack overflows when cyclic references exist.
7918 if (g_hash_table_lookup (visited_images, image))
7921 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7923 if ((nested = strchr (name, '/'))) {
7924 int pos = nested - name;
7925 int len = strlen (name);
7928 memcpy (buf, name, len + 1);
7930 nested = buf + pos + 1;
7934 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7935 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7936 gboolean res = get_class_from_name (image, name_space, name, &klass);
7939 klass = search_modules (image, name_space, name, error);
7944 return klass ? return_nested_in (klass, nested) : NULL;
7950 mono_image_init_name_cache (image);
7951 mono_image_lock (image);
7953 nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7956 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7958 mono_image_unlock (image);
7960 if (!token && image_is_dynamic (image) && image->modules) {
7961 /* Search modules as well */
7962 for (i = 0; i < image->module_count; ++i) {
7963 MonoImage *module = image->modules [i];
7965 klass = mono_class_from_name_checked (module, name_space, name, error);
7966 if (klass || !is_ok (error))
7972 klass = search_modules (image, name_space, name, error);
7973 if (klass || !is_ok (error))
7978 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7979 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7980 guint32 cols [MONO_EXP_TYPE_SIZE];
7983 idx = mono_metadata_token_index (token);
7985 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7987 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7988 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7989 loaded_image = mono_assembly_load_module_checked (image->assembly, impl >> MONO_IMPLEMENTATION_BITS, error);
7992 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7994 return klass ? return_nested_in (klass, nested) : NULL;
7996 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7997 guint32 assembly_idx;
7999 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
8001 mono_assembly_load_reference (image, assembly_idx - 1);
8002 g_assert (image->references [assembly_idx - 1]);
8003 if (image->references [assembly_idx - 1] == (gpointer)-1)
8005 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
8007 return klass ? return_nested_in (klass, nested) : NULL;
8010 g_assert_not_reached ();
8014 token = MONO_TOKEN_TYPE_DEF | token;
8016 klass = mono_class_get_checked (image, token, error);
8018 return return_nested_in (klass, nested);
8023 * mono_class_from_name_checked:
8024 * @image: The MonoImage where the type is looked up in
8025 * @name_space: the type namespace
8026 * @name: the type short name.
8028 * Obtains a MonoClass with a given namespace and a given name which
8029 * is located in the given MonoImage.
8031 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
8032 * set if the class was not found or it will return NULL and set the error if there was a loading error.
8035 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
8038 GHashTable *visited_images;
8040 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
8042 klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
8044 g_hash_table_destroy (visited_images);
8050 * mono_class_from_name:
8051 * @image: The MonoImage where the type is looked up in
8052 * @name_space: the type namespace
8053 * @name: the type short name.
8055 * Obtains a MonoClass with a given namespace and a given name which
8056 * is located in the given MonoImage.
8058 * To reference nested classes, use the "/" character as a separator.
8059 * For example use "Foo/Bar" to reference the class Bar that is nested
8060 * inside Foo, like this: "class Foo { class Bar {} }".
8063 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
8068 klass = mono_class_from_name_checked (image, name_space, name, &error);
8069 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
8075 * mono_class_load_from_name:
8076 * @image: The MonoImage where the type is looked up in
8077 * @name_space: the type namespace
8078 * @name: the type short name.
8080 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
8081 * This function should be used by the runtime for critical types to which there's no way to recover but crash
8082 * If they are missing. Thing of System.Object or System.String.
8085 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
8090 klass = mono_class_from_name_checked (image, name_space, name, &error);
8092 g_error ("Runtime critical type %s.%s not found", name_space, name);
8093 if (!mono_error_ok (&error))
8094 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8099 * mono_class_try_load_from_name:
8100 * @image: The MonoImage where the type is looked up in
8101 * @name_space: the type namespace
8102 * @name: the type short name.
8104 * This function tries to load a type, returning the class was found or NULL otherwise.
8105 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
8107 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
8108 * a type that we would otherwise assume to be available but was not due some error.
8112 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
8117 klass = mono_class_from_name_checked (image, name_space, name, &error);
8118 if (!mono_error_ok (&error))
8119 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8125 * mono_class_is_subclass_of:
8126 * @klass: class to probe if it is a subclass of another one
8127 * @klassc: the class we suspect is the base class
8128 * @check_interfaces: whether we should perform interface checks
8130 * This method determines whether @klass is a subclass of @klassc.
8132 * If the @check_interfaces flag is set, then if @klassc is an interface
8133 * this method return TRUE if the @klass implements the interface or
8134 * if @klass is an interface, if one of its base classes is @klass.
8136 * If @check_interfaces is false then, then if @klass is not an interface
8137 * then it returns TRUE if the @klass is a subclass of @klassc.
8139 * if @klass is an interface and @klassc is System.Object, then this function
8144 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
8145 gboolean check_interfaces)
8147 /* FIXME test for interfaces with variant generic arguments */
8148 mono_class_init (klass);
8149 mono_class_init (klassc);
8151 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
8152 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
8154 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
8157 for (i = 0; i < klass->interface_count; i ++) {
8158 MonoClass *ic = klass->interfaces [i];
8163 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
8168 * MS.NET thinks interfaces are a subclass of Object, so we think it as
8171 if (klassc == mono_defaults.object_class)
8178 mono_type_is_generic_argument (MonoType *type)
8180 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
8184 mono_class_has_variant_generic_params (MonoClass *klass)
8187 MonoGenericContainer *container;
8189 if (!mono_class_is_ginst (klass))
8192 container = mono_class_get_generic_container (mono_class_get_generic_class (klass)->container_class);
8194 for (i = 0; i < container->type_argc; ++i)
8195 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8202 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8204 if (target == candidate)
8207 if (check_for_reference_conv &&
8208 mono_type_is_generic_argument (&target->byval_arg) &&
8209 mono_type_is_generic_argument (&candidate->byval_arg)) {
8210 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8211 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8213 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8216 if (!mono_class_is_assignable_from (target, candidate))
8222 * @container the generic container from the GTD
8223 * @klass: the class to be assigned to
8224 * @oklass: the source class
8226 * Both @klass and @oklass must be instances of the same generic interface.
8228 * Returns: TRUE if @klass can be assigned to a @klass variable
8231 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8234 MonoType **klass_argv, **oklass_argv;
8235 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8236 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8238 if (klass == oklass)
8241 /*Viable candidates are instances of the same generic interface*/
8242 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8245 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8246 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8248 for (j = 0; j < container->type_argc; ++j) {
8249 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8250 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8252 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8256 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8257 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8259 if (param1_class != param2_class) {
8260 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8261 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8263 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8264 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8274 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8276 MonoGenericParam *gparam, *ogparam;
8277 MonoGenericParamInfo *tinfo, *cinfo;
8278 MonoClass **candidate_class;
8279 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8282 if (target == candidate)
8284 if (target->byval_arg.type != candidate->byval_arg.type)
8287 gparam = target->byval_arg.data.generic_param;
8288 ogparam = candidate->byval_arg.data.generic_param;
8289 tinfo = mono_generic_param_info (gparam);
8290 cinfo = mono_generic_param_info (ogparam);
8292 class_constraint_satisfied = FALSE;
8293 valuetype_constraint_satisfied = FALSE;
8295 /*candidate must have a super set of target's special constraints*/
8296 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8297 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8299 if (cinfo->constraints) {
8300 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8301 MonoClass *cc = *candidate_class;
8303 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8304 class_constraint_satisfied = TRUE;
8305 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8306 valuetype_constraint_satisfied = TRUE;
8309 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8310 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8312 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8314 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8316 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8317 valuetype_constraint_satisfied)) {
8322 /*candidate type constraints must be a superset of target's*/
8323 if (tinfo->constraints) {
8324 MonoClass **target_class;
8325 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8326 MonoClass *tc = *target_class;
8329 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8330 * check it's constraints since it satisfy the constraint by itself.
8332 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8335 if (!cinfo->constraints)
8338 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8339 MonoClass *cc = *candidate_class;
8341 if (mono_class_is_assignable_from (tc, cc))
8345 * This happens when we have the following:
8347 * Bar<K> where K : IFace
8348 * Foo<T, U> where T : U where U : IFace
8350 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8353 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8354 if (mono_gparam_is_assignable_from (target, cc))
8358 if (!*candidate_class)
8363 /*candidate itself must have a constraint that satisfy target*/
8364 if (cinfo->constraints) {
8365 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8366 MonoClass *cc = *candidate_class;
8367 if (mono_class_is_assignable_from (target, cc))
8375 * mono_class_is_assignable_from:
8376 * @klass: the class to be assigned to
8377 * @oklass: the source class
8379 * Returns: TRUE if an instance of object oklass can be assigned to an
8380 * instance of object @klass
8383 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8386 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8388 mono_class_init (klass);
8390 if (!oklass->inited)
8391 mono_class_init (oklass);
8393 if (mono_class_has_failure (klass) || mono_class_has_failure (oklass))
8396 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8397 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8399 return mono_gparam_is_assignable_from (klass, oklass);
8402 if (MONO_CLASS_IS_INTERFACE (klass)) {
8403 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8404 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8405 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8409 for (i = 0; constraints [i]; ++i) {
8410 if (mono_class_is_assignable_from (klass, constraints [i]))
8418 /* interface_offsets might not be set for dynamic classes */
8419 if (mono_class_get_ref_info_handle (oklass) && !oklass->interface_bitmap) {
8421 * oklass might be a generic type parameter but they have
8422 * interface_offsets set.
8424 gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8425 if (!is_ok (&error)) {
8426 mono_error_cleanup (&error);
8431 if (!oklass->interface_bitmap)
8432 /* Happens with generic instances of not-yet created dynamic types */
8434 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8437 if (mono_class_has_variant_generic_params (klass)) {
8439 mono_class_setup_interfaces (oklass, &error);
8440 if (!mono_error_ok (&error)) {
8441 mono_error_cleanup (&error);
8445 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8446 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8447 MonoClass *iface = oklass->interfaces_packed [i];
8449 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8454 } else if (klass->delegate) {
8455 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8457 }else if (klass->rank) {
8458 MonoClass *eclass, *eoclass;
8460 if (oklass->rank != klass->rank)
8463 /* vectors vs. one dimensional arrays */
8464 if (oklass->byval_arg.type != klass->byval_arg.type)
8467 eclass = klass->cast_class;
8468 eoclass = oklass->cast_class;
8471 * a is b does not imply a[] is b[] when a is a valuetype, and
8472 * b is a reference type.
8475 if (eoclass->valuetype) {
8476 if ((eclass == mono_defaults.enum_class) ||
8477 (eclass == mono_defaults.enum_class->parent) ||
8478 (eclass == mono_defaults.object_class))
8482 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8483 } else if (mono_class_is_nullable (klass)) {
8484 if (mono_class_is_nullable (oklass))
8485 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8487 return mono_class_is_assignable_from (klass->cast_class, oklass);
8488 } else if (klass == mono_defaults.object_class)
8491 return mono_class_has_parent (oklass, klass);
8494 /*Check if @oklass is variant compatible with @klass.*/
8496 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8499 MonoType **klass_argv, **oklass_argv;
8500 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8501 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8503 /*Viable candidates are instances of the same generic interface*/
8504 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8507 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8508 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8510 for (j = 0; j < container->type_argc; ++j) {
8511 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8512 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8514 if (param1_class->valuetype != param2_class->valuetype)
8518 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8519 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8521 if (param1_class != param2_class) {
8522 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8523 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8525 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8526 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8534 /*Check if @candidate implements the interface @target*/
8536 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8540 gboolean is_variant = mono_class_has_variant_generic_params (target);
8542 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8543 if (mono_class_is_variant_compatible_slow (target, candidate))
8548 if (candidate == target)
8551 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8552 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8553 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (candidate);
8555 if (tb && tb->interfaces) {
8556 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8557 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8558 MonoClass *iface_class;
8560 /* we can't realize the type here since it can do pretty much anything. */
8563 iface_class = mono_class_from_mono_type (iface->type);
8564 if (iface_class == target)
8566 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8568 if (mono_class_implement_interface_slow (target, iface_class))
8573 /*setup_interfaces don't mono_class_init anything*/
8574 /*FIXME this doesn't handle primitive type arrays.
8575 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8576 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8578 mono_class_setup_interfaces (candidate, &error);
8579 if (!mono_error_ok (&error)) {
8580 mono_error_cleanup (&error);
8584 for (i = 0; i < candidate->interface_count; ++i) {
8585 if (candidate->interfaces [i] == target)
8588 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8591 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8595 candidate = candidate->parent;
8596 } while (candidate);
8602 * Check if @oklass can be assigned to @klass.
8603 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8606 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8608 if (candidate == target)
8610 if (target == mono_defaults.object_class)
8613 if (mono_class_has_parent (candidate, target))
8616 /*If target is not an interface there is no need to check them.*/
8617 if (MONO_CLASS_IS_INTERFACE (target))
8618 return mono_class_implement_interface_slow (target, candidate);
8620 if (target->delegate && mono_class_has_variant_generic_params (target))
8621 return mono_class_is_variant_compatible (target, candidate, FALSE);
8624 MonoClass *eclass, *eoclass;
8626 if (target->rank != candidate->rank)
8629 /* vectors vs. one dimensional arrays */
8630 if (target->byval_arg.type != candidate->byval_arg.type)
8633 eclass = target->cast_class;
8634 eoclass = candidate->cast_class;
8637 * a is b does not imply a[] is b[] when a is a valuetype, and
8638 * b is a reference type.
8641 if (eoclass->valuetype) {
8642 if ((eclass == mono_defaults.enum_class) ||
8643 (eclass == mono_defaults.enum_class->parent) ||
8644 (eclass == mono_defaults.object_class))
8648 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8650 /*FIXME properly handle nullables */
8651 /*FIXME properly handle (M)VAR */
8656 * mono_class_get_cctor:
8657 * @klass: A MonoClass pointer
8659 * Returns: The static constructor of @klass if it exists, NULL otherwise.
8662 mono_class_get_cctor (MonoClass *klass)
8664 MonoCachedClassInfo cached_info;
8666 if (image_is_dynamic (klass->image)) {
8668 * has_cctor is not set for these classes because mono_class_init () is
8671 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8674 if (!klass->has_cctor)
8677 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8679 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8680 if (!mono_error_ok (&error))
8681 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8685 if (mono_class_is_ginst (klass) && !klass->methods)
8686 return mono_class_get_inflated_method (klass, mono_class_get_cctor (mono_class_get_generic_class (klass)->container_class));
8688 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8692 * mono_class_get_finalizer:
8693 * @klass: The MonoClass pointer
8695 * Returns: The finalizer method of @klass if it exists, NULL otherwise.
8698 mono_class_get_finalizer (MonoClass *klass)
8700 MonoCachedClassInfo cached_info;
8703 mono_class_init (klass);
8704 if (!mono_class_has_finalizer (klass))
8707 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8709 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8710 if (!mono_error_ok (&error))
8711 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8714 mono_class_setup_vtable (klass);
8715 return klass->vtable [finalize_slot];
8720 * mono_class_needs_cctor_run:
8721 * @klass: the MonoClass pointer
8722 * @caller: a MonoMethod describing the caller
8724 * Determines whenever the class has a static constructor and whenever it
8725 * needs to be called when executing CALLER.
8728 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8732 method = mono_class_get_cctor (klass);
8734 return (method == caller) ? FALSE : TRUE;
8740 * mono_class_array_element_size:
8743 * Returns: The number of bytes an element of type @klass
8744 * uses when stored into an array.
8747 mono_class_array_element_size (MonoClass *klass)
8749 MonoType *type = &klass->byval_arg;
8752 switch (type->type) {
8755 case MONO_TYPE_BOOLEAN:
8759 case MONO_TYPE_CHAR:
8768 case MONO_TYPE_CLASS:
8769 case MONO_TYPE_STRING:
8770 case MONO_TYPE_OBJECT:
8771 case MONO_TYPE_SZARRAY:
8772 case MONO_TYPE_ARRAY:
8773 return sizeof (gpointer);
8778 case MONO_TYPE_VALUETYPE:
8779 if (type->data.klass->enumtype) {
8780 type = mono_class_enum_basetype (type->data.klass);
8781 klass = klass->element_class;
8784 return mono_class_instance_size (klass) - sizeof (MonoObject);
8785 case MONO_TYPE_GENERICINST:
8786 type = &type->data.generic_class->container_class->byval_arg;
8789 case MONO_TYPE_MVAR: {
8792 return mono_type_size (type, &align);
8794 case MONO_TYPE_VOID:
8798 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8804 * mono_array_element_size:
8805 * @ac: pointer to a #MonoArrayClass
8807 * Returns: The size of single array element.
8810 mono_array_element_size (MonoClass *ac)
8812 g_assert (ac->rank);
8813 return ac->sizes.element_size;
8817 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8818 MonoGenericContext *context)
8821 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8822 g_assert (mono_error_ok (&error));
8827 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8828 MonoGenericContext *context, MonoError *error)
8830 mono_error_init (error);
8832 if (image_is_dynamic (image)) {
8833 MonoClass *tmp_handle_class;
8834 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
8836 mono_error_assert_ok (error);
8837 g_assert (tmp_handle_class);
8839 *handle_class = tmp_handle_class;
8841 if (tmp_handle_class == mono_defaults.typehandle_class)
8842 return &((MonoClass*)obj)->byval_arg;
8847 switch (token & 0xff000000) {
8848 case MONO_TOKEN_TYPE_DEF:
8849 case MONO_TOKEN_TYPE_REF:
8850 case MONO_TOKEN_TYPE_SPEC: {
8853 *handle_class = mono_defaults.typehandle_class;
8854 type = mono_type_get_checked (image, token, context, error);
8858 mono_class_init (mono_class_from_mono_type (type));
8859 /* We return a MonoType* as handle */
8862 case MONO_TOKEN_FIELD_DEF: {
8864 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8866 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8870 *handle_class = mono_defaults.fieldhandle_class;
8871 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8875 mono_class_init (klass);
8876 return mono_class_get_field (klass, token);
8878 case MONO_TOKEN_METHOD_DEF:
8879 case MONO_TOKEN_METHOD_SPEC: {
8881 meth = mono_get_method_checked (image, token, NULL, context, error);
8883 *handle_class = mono_defaults.methodhandle_class;
8889 case MONO_TOKEN_MEMBER_REF: {
8890 guint32 cols [MONO_MEMBERREF_SIZE];
8892 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8893 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8894 mono_metadata_decode_blob_size (sig, &sig);
8895 if (*sig == 0x6) { /* it's a field */
8897 MonoClassField *field;
8898 field = mono_field_from_token_checked (image, token, &klass, context, error);
8900 *handle_class = mono_defaults.fieldhandle_class;
8904 meth = mono_get_method_checked (image, token, NULL, context, error);
8906 *handle_class = mono_defaults.methodhandle_class;
8911 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8917 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
8919 MonoClass *handle_class;
8920 mono_error_init (error);
8921 return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
8925 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
8927 return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
8930 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8933 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8935 get_cached_class_info = func;
8939 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8941 if (!get_cached_class_info)
8944 return get_cached_class_info (klass, res);
8948 mono_install_get_class_from_name (MonoGetClassFromName func)
8950 get_class_from_name = func;
8954 * mono_class_get_image:
8956 * Use this method to get the `MonoImage*` where this class came from.
8958 * Returns: The image where this class is defined.
8961 mono_class_get_image (MonoClass *klass)
8963 return klass->image;
8967 * mono_class_get_element_class:
8968 * @klass: the MonoClass to act on
8970 * Use this function to get the element class of an array.
8972 * Returns: The element class of an array.
8975 mono_class_get_element_class (MonoClass *klass)
8977 return klass->element_class;
8981 * mono_class_is_valuetype:
8982 * @klass: the MonoClass to act on
8984 * Use this method to determine if the provided `MonoClass*` represents a value type,
8985 * or a reference type.
8987 * Returns: TRUE if the MonoClass represents a ValueType, FALSE if it represents a reference type.
8990 mono_class_is_valuetype (MonoClass *klass)
8992 return klass->valuetype;
8996 * mono_class_is_enum:
8997 * @klass: the MonoClass to act on
8999 * Use this function to determine if the provided `MonoClass*` represents an enumeration.
9001 * Returns: TRUE if the MonoClass represents an enumeration.
9004 mono_class_is_enum (MonoClass *klass)
9006 return klass->enumtype;
9010 * mono_class_enum_basetype:
9011 * @klass: the MonoClass to act on
9013 * Use this function to get the underlying type for an enumeration value.
9015 * Returns: The underlying type representation for an enumeration.
9018 mono_class_enum_basetype (MonoClass *klass)
9020 if (klass->element_class == klass)
9021 /* SRE or broken types */
9024 return &klass->element_class->byval_arg;
9028 * mono_class_get_parent
9029 * @klass: the MonoClass to act on
9031 * Returns: The parent class for this class.
9034 mono_class_get_parent (MonoClass *klass)
9036 return klass->parent;
9040 * mono_class_get_nesting_type:
9041 * @klass: the MonoClass to act on
9043 * Use this function to obtain the class that the provided `MonoClass*` is nested on.
9045 * If the return is NULL, this indicates that this class is not nested.
9047 * Returns: The container type where this type is nested or NULL if this type is not a nested type.
9050 mono_class_get_nesting_type (MonoClass *klass)
9052 return klass->nested_in;
9056 * mono_class_get_rank:
9057 * @klass: the MonoClass to act on
9059 * Returns: The rank for the array (the number of dimensions).
9062 mono_class_get_rank (MonoClass *klass)
9068 * mono_class_get_name
9069 * @klass: the MonoClass to act on
9071 * Returns: The name of the class.
9074 mono_class_get_name (MonoClass *klass)
9080 * mono_class_get_namespace:
9081 * @klass: the MonoClass to act on
9083 * Returns: The namespace of the class.
9086 mono_class_get_namespace (MonoClass *klass)
9088 return klass->name_space;
9092 * mono_class_get_type:
9093 * @klass: the MonoClass to act on
9095 * This method returns the internal Type representation for the class.
9097 * Returns: The MonoType from the class.
9100 mono_class_get_type (MonoClass *klass)
9102 return &klass->byval_arg;
9106 * mono_class_get_type_token:
9107 * @klass: the MonoClass to act on
9109 * This method returns type token for the class.
9111 * Returns: The type token for the class.
9114 mono_class_get_type_token (MonoClass *klass)
9116 return klass->type_token;
9120 * mono_class_get_byref_type:
9121 * @klass: the MonoClass to act on
9126 mono_class_get_byref_type (MonoClass *klass)
9128 return &klass->this_arg;
9132 * mono_class_num_fields:
9133 * @klass: the MonoClass to act on
9135 * Returns: The number of static and instance fields in the class.
9138 mono_class_num_fields (MonoClass *klass)
9140 return mono_class_get_field_count (klass);
9144 * mono_class_num_methods:
9145 * @klass: the MonoClass to act on
9147 * Returns: The number of methods in the class.
9150 mono_class_num_methods (MonoClass *klass)
9152 return mono_class_get_method_count (klass);
9156 * mono_class_num_properties
9157 * @klass: the MonoClass to act on
9159 * Returns: The number of properties in the class.
9162 mono_class_num_properties (MonoClass *klass)
9164 mono_class_setup_properties (klass);
9166 return mono_class_get_ext (klass)->property.count;
9170 * mono_class_num_events:
9171 * @klass: the MonoClass to act on
9173 * Returns: The number of events in the class.
9176 mono_class_num_events (MonoClass *klass)
9178 mono_class_setup_events (klass);
9180 return mono_class_get_ext (klass)->event.count;
9184 * mono_class_get_fields:
9185 * @klass: the MonoClass to act on
9187 * This routine is an iterator routine for retrieving the fields in a class.
9189 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9190 * iterate over all of the elements. When no more values are
9191 * available, the return value is NULL.
9193 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
9196 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9198 MonoClassField* field;
9202 mono_class_setup_fields (klass);
9203 if (mono_class_has_failure (klass))
9205 /* start from the first */
9206 if (mono_class_get_field_count (klass)) {
9207 *iter = &klass->fields [0];
9208 return &klass->fields [0];
9214 field = (MonoClassField *)*iter;
9216 if (field < &klass->fields [mono_class_get_field_count (klass)]) {
9224 * mono_class_get_methods
9225 * @klass: the MonoClass to act on
9227 * This routine is an iterator routine for retrieving the fields in a class.
9229 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9230 * iterate over all of the elements. When no more values are
9231 * available, the return value is NULL.
9233 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
9236 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9238 MonoMethod** method;
9242 mono_class_setup_methods (klass);
9245 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9246 * FIXME we should better report this error to the caller
9248 if (!klass->methods)
9250 /* start from the first */
9251 if (mono_class_get_method_count (klass)) {
9252 *iter = &klass->methods [0];
9253 return klass->methods [0];
9259 method = (MonoMethod **)*iter;
9261 if (method < &klass->methods [mono_class_get_method_count (klass)]) {
9269 * mono_class_get_virtual_methods:
9271 * Iterate over the virtual methods of KLASS.
9273 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9276 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9278 MonoMethod** method;
9281 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9283 mono_class_setup_methods (klass);
9285 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9286 * FIXME we should better report this error to the caller
9288 if (!klass->methods)
9290 /* start from the first */
9291 method = &klass->methods [0];
9293 method = (MonoMethod **)*iter;
9296 int mcount = mono_class_get_method_count (klass);
9297 while (method < &klass->methods [mcount]) {
9298 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9302 if (method < &klass->methods [mcount]) {
9309 /* Search directly in metadata to avoid calling setup_methods () */
9310 MonoMethod *res = NULL;
9316 start_index = GPOINTER_TO_UINT (*iter);
9319 int first_idx = mono_class_get_first_method_idx (klass);
9320 int mcount = mono_class_get_method_count (klass);
9321 for (i = start_index; i < mcount; ++i) {
9324 /* first_idx points into the methodptr table */
9325 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
9327 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9333 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9334 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9336 /* Add 1 here so the if (*iter) check fails */
9337 *iter = GUINT_TO_POINTER (i + 1);
9346 * mono_class_get_properties:
9347 * @klass: the MonoClass to act on
9349 * This routine is an iterator routine for retrieving the properties in a class.
9351 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9352 * iterate over all of the elements. When no more values are
9353 * available, the return value is NULL.
9355 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9358 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9360 MonoProperty* property;
9364 mono_class_setup_properties (klass);
9365 MonoClassExt *ext = mono_class_get_ext (klass);
9366 /* start from the first */
9367 if (ext->property.count) {
9368 *iter = &ext->properties [0];
9369 return (MonoProperty *)*iter;
9375 property = (MonoProperty *)*iter;
9377 MonoClassExt *ext = mono_class_get_ext (klass);
9378 if (property < &ext->properties [ext->property.count]) {
9380 return (MonoProperty *)*iter;
9386 * mono_class_get_events:
9387 * @klass: the MonoClass to act on
9389 * This routine is an iterator routine for retrieving the properties in a class.
9391 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9392 * iterate over all of the elements. When no more values are
9393 * available, the return value is NULL.
9395 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9398 mono_class_get_events (MonoClass* klass, gpointer *iter)
9404 mono_class_setup_events (klass);
9405 MonoClassExt *ext = mono_class_get_ext (klass);
9406 /* start from the first */
9407 if (ext->event.count) {
9408 *iter = &ext->events [0];
9409 return (MonoEvent *)*iter;
9415 event = (MonoEvent *)*iter;
9417 MonoClassExt *ext = mono_class_get_ext (klass);
9418 if (event < &ext->events [ext->event.count]) {
9420 return (MonoEvent *)*iter;
9426 * mono_class_get_interfaces
9427 * @klass: the MonoClass to act on
9429 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9431 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9432 * iterate over all of the elements. When no more values are
9433 * available, the return value is NULL.
9435 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9438 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9446 mono_class_init (klass);
9447 if (!klass->interfaces_inited) {
9448 mono_class_setup_interfaces (klass, &error);
9449 if (!mono_error_ok (&error)) {
9450 mono_error_cleanup (&error);
9454 /* start from the first */
9455 if (klass->interface_count) {
9456 *iter = &klass->interfaces [0];
9457 return klass->interfaces [0];
9463 iface = (MonoClass **)*iter;
9465 if (iface < &klass->interfaces [klass->interface_count]) {
9473 setup_nested_types (MonoClass *klass)
9476 GList *classes, *nested_classes, *l;
9479 if (klass->nested_classes_inited)
9482 if (!klass->type_token)
9483 klass->nested_classes_inited = TRUE;
9485 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9489 guint32 cols [MONO_NESTED_CLASS_SIZE];
9490 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9491 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9492 if (!mono_error_ok (&error)) {
9493 /*FIXME don't swallow the error message*/
9494 mono_error_cleanup (&error);
9496 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9500 classes = g_list_prepend (classes, nclass);
9502 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9505 mono_class_alloc_ext (klass);
9507 nested_classes = NULL;
9508 for (l = classes; l; l = l->next)
9509 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9510 g_list_free (classes);
9512 mono_image_lock (klass->image);
9514 mono_memory_barrier ();
9515 if (!klass->nested_classes_inited) {
9516 mono_class_get_ext (klass)->nested_classes = nested_classes;
9517 mono_memory_barrier ();
9518 klass->nested_classes_inited = TRUE;
9521 mono_image_unlock (klass->image);
9525 * mono_class_get_nested_types
9526 * @klass: the MonoClass to act on
9528 * This routine is an iterator routine for retrieving the nested types of a class.
9529 * This works only if @klass is non-generic, or a generic type definition.
9531 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9532 * iterate over all of the elements. When no more values are
9533 * available, the return value is NULL.
9535 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9538 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9544 if (!klass->nested_classes_inited)
9545 setup_nested_types (klass);
9548 MonoClassExt *ext = mono_class_get_ext (klass);
9549 /* start from the first */
9550 if (ext && ext->nested_classes) {
9551 *iter = ext->nested_classes;
9552 return (MonoClass *)ext->nested_classes->data;
9554 /* no nested types */
9558 item = (GList *)*iter;
9562 return (MonoClass *)item->data;
9569 * mono_class_is_delegate
9570 * @klass: the MonoClass to act on
9572 * Returns: TRUE if the MonoClass represents a System.Delegate.
9575 mono_class_is_delegate (MonoClass *klass)
9577 return klass->delegate;
9581 * mono_class_implements_interface
9582 * @klass: The MonoClass to act on
9583 * @interface: The interface to check if @klass implements.
9585 * Returns: TRUE if @klass implements @interface.
9588 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9590 return mono_class_is_assignable_from (iface, klass);
9594 * mono_field_get_name:
9595 * @field: the MonoClassField to act on
9597 * Returns: The name of the field.
9600 mono_field_get_name (MonoClassField *field)
9606 * mono_field_get_type:
9607 * @field: the MonoClassField to act on
9609 * Returns: MonoType of the field.
9612 mono_field_get_type (MonoClassField *field)
9615 MonoType *type = mono_field_get_type_checked (field, &error);
9616 if (!mono_error_ok (&error)) {
9617 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9618 mono_error_cleanup (&error);
9625 * mono_field_get_type_checked:
9626 * @field: the MonoClassField to act on
9627 * @error: used to return any erro found while retrieving @field type
9629 * Returns: MonoType of the field.
9632 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9634 mono_error_init (error);
9636 mono_field_resolve_type (field, error);
9641 * mono_field_get_parent:
9642 * @field: the MonoClassField to act on
9644 * Returns: MonoClass where the field was defined.
9647 mono_field_get_parent (MonoClassField *field)
9649 return field->parent;
9653 * mono_field_get_flags;
9654 * @field: the MonoClassField to act on
9656 * The metadata flags for a field are encoded using the
9657 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9659 * Returns: The flags for the field.
9662 mono_field_get_flags (MonoClassField *field)
9665 return mono_field_resolve_flags (field);
9666 return field->type->attrs;
9670 * mono_field_get_offset:
9671 * @field: the MonoClassField to act on
9673 * Returns: The field offset.
9676 mono_field_get_offset (MonoClassField *field)
9678 return field->offset;
9682 mono_field_get_rva (MonoClassField *field)
9686 MonoClass *klass = field->parent;
9687 MonoFieldDefaultValue *field_def_values;
9689 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9691 MonoClassExt *ext = mono_class_get_ext (klass);
9692 if (!ext || !ext->field_def_values) {
9693 mono_class_alloc_ext (klass);
9694 ext = mono_class_get_ext (klass);
9696 field_def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
9698 mono_image_lock (klass->image);
9699 if (!ext->field_def_values)
9700 ext->field_def_values = field_def_values;
9701 mono_image_unlock (klass->image);
9704 field_index = mono_field_get_index (field);
9706 if (!ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9707 int first_field_idx = mono_class_get_first_field_idx (klass);
9708 mono_metadata_field_info (field->parent->image, first_field_idx + field_index, NULL, &rva, NULL);
9710 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9711 ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9714 return ext->field_def_values [field_index].data;
9718 * mono_field_get_data:
9719 * @field: the MonoClassField to act on
9721 * Returns: A pointer to the metadata constant value or to the field
9722 * data if it has an RVA flag.
9725 mono_field_get_data (MonoClassField *field)
9727 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9728 MonoTypeEnum def_type;
9730 return mono_class_get_field_default_value (field, &def_type);
9731 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9732 return mono_field_get_rva (field);
9739 * mono_property_get_name:
9740 * @prop: the MonoProperty to act on
9742 * Returns: The name of the property
9745 mono_property_get_name (MonoProperty *prop)
9751 * mono_property_get_set_method
9752 * @prop: the MonoProperty to act on.
9754 * Returns: The setter method of the property (A MonoMethod)
9757 mono_property_get_set_method (MonoProperty *prop)
9763 * mono_property_get_get_method
9764 * @prop: the MonoProperty to act on.
9766 * Returns: The setter method of the property (A MonoMethod)
9769 mono_property_get_get_method (MonoProperty *prop)
9775 * mono_property_get_parent:
9776 * @prop: the MonoProperty to act on.
9778 * Returns: The MonoClass where the property was defined.
9781 mono_property_get_parent (MonoProperty *prop)
9783 return prop->parent;
9787 * mono_property_get_flags:
9788 * @prop: the MonoProperty to act on.
9790 * The metadata flags for a property are encoded using the
9791 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9793 * Returns: The flags for the property.
9796 mono_property_get_flags (MonoProperty *prop)
9802 * mono_event_get_name:
9803 * @event: the MonoEvent to act on
9805 * Returns: The name of the event.
9808 mono_event_get_name (MonoEvent *event)
9814 * mono_event_get_add_method:
9815 * @event: The MonoEvent to act on.
9817 * Returns: The @add' method for the event (a MonoMethod).
9820 mono_event_get_add_method (MonoEvent *event)
9826 * mono_event_get_remove_method:
9827 * @event: The MonoEvent to act on.
9829 * Returns: The @remove method for the event (a MonoMethod).
9832 mono_event_get_remove_method (MonoEvent *event)
9834 return event->remove;
9838 * mono_event_get_raise_method:
9839 * @event: The MonoEvent to act on.
9841 * Returns: The @raise method for the event (a MonoMethod).
9844 mono_event_get_raise_method (MonoEvent *event)
9846 return event->raise;
9850 * mono_event_get_parent:
9851 * @event: the MonoEvent to act on.
9853 * Returns: The MonoClass where the event is defined.
9856 mono_event_get_parent (MonoEvent *event)
9858 return event->parent;
9862 * mono_event_get_flags
9863 * @event: the MonoEvent to act on.
9865 * The metadata flags for an event are encoded using the
9866 * EVENT_* constants. See the tabledefs.h file for details.
9868 * Returns: The flags for the event.
9871 mono_event_get_flags (MonoEvent *event)
9873 return event->attrs;
9877 * mono_class_get_method_from_name:
9878 * @klass: where to look for the method
9879 * @name: name of the method
9880 * @param_count: number of parameters. -1 for any number.
9882 * Obtains a MonoMethod with a given name and number of parameters.
9883 * It only works if there are no multiple signatures for any given method name.
9886 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9888 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9892 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9894 MonoMethod *res = NULL;
9897 /* Search directly in the metadata to avoid calling setup_methods () */
9898 int first_idx = mono_class_get_first_method_idx (klass);
9899 int mcount = mono_class_get_method_count (klass);
9900 for (i = 0; i < mcount; ++i) {
9902 guint32 cols [MONO_METHOD_SIZE];
9904 MonoMethodSignature *sig;
9906 /* first_idx points into the methodptr table */
9907 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, first_idx + i, cols, MONO_METHOD_SIZE);
9909 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9910 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9912 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9915 if (param_count == -1) {
9919 sig = mono_method_signature_checked (method, &error);
9921 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9924 if (sig->param_count == param_count) {
9935 * mono_class_get_method_from_name_flags:
9936 * @klass: where to look for the method
9937 * @name_space: name of the method
9938 * @param_count: number of parameters. -1 for any number.
9939 * @flags: flags which must be set in the method
9941 * Obtains a MonoMethod with a given name and number of parameters.
9942 * It only works if there are no multiple signatures for any given method name.
9945 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9947 MonoMethod *res = NULL;
9950 mono_class_init (klass);
9952 if (mono_class_is_ginst (klass) && !klass->methods) {
9953 res = mono_class_get_method_from_name_flags (mono_class_get_generic_class (klass)->container_class, name, param_count, flags);
9956 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9957 if (!mono_error_ok (&error))
9958 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9963 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9964 mono_class_setup_methods (klass);
9966 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9967 See mono/tests/array_load_exception.il
9968 FIXME we should better report this error to the caller
9970 if (!klass->methods)
9972 int mcount = mono_class_get_method_count (klass);
9973 for (i = 0; i < mcount; ++i) {
9974 MonoMethod *method = klass->methods [i];
9976 if (method->name[0] == name [0] &&
9977 !strcmp (name, method->name) &&
9978 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9979 ((method->flags & flags) == flags)) {
9986 res = find_method_in_metadata (klass, name, param_count, flags);
9993 * mono_class_set_failure:
9994 * @klass: class in which the failure was detected
9995 * @ex_type: the kind of exception/error to be thrown (later)
9996 * @ex_data: exception data (specific to each type of exception/error)
9998 * Keep a detected failure informations in the class for later processing.
9999 * Note that only the first failure is kept.
10001 * LOCKING: Acquires the loader lock.
10004 mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error)
10006 g_assert (boxed_error != NULL);
10008 if (mono_class_has_failure (klass))
10011 mono_loader_lock ();
10012 klass->has_failure = 1;
10013 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, boxed_error);
10014 mono_loader_unlock ();
10020 mono_class_has_failure (const MonoClass *klass)
10022 g_assert (klass != NULL);
10023 return klass->has_failure != 0;
10028 * mono_class_set_type_load_failure:
10029 * @klass: class in which the failure was detected
10030 * @fmt: Printf-style error message string.
10032 * Collect detected failure informaion in the class for later processing.
10033 * The error is stored as a MonoErrorBoxed as with mono_error_set_type_load_class ()
10034 * Note that only the first failure is kept.
10036 * Returns FALSE if a failure was already set on the class, or TRUE otherwise.
10038 * LOCKING: Acquires the loader lock.
10041 mono_class_set_type_load_failure (MonoClass *klass, const char * fmt, ...)
10043 MonoError prepare_error;
10046 if (mono_class_has_failure (klass))
10049 mono_error_init (&prepare_error);
10051 va_start (args, fmt);
10052 mono_error_vset_type_load_class (&prepare_error, klass, fmt, args);
10055 MonoErrorBoxed *box = mono_error_box (&prepare_error, klass->image);
10056 mono_error_cleanup (&prepare_error);
10057 return mono_class_set_failure (klass, box);
10061 * mono_class_get_exception_data:
10063 * Return the exception_data property of KLASS.
10065 * LOCKING: Acquires the loader lock.
10068 mono_class_get_exception_data (const MonoClass *klass)
10070 return mono_image_property_lookup (klass->image, (MonoClass*)klass, MONO_CLASS_PROP_EXCEPTION_DATA);
10074 * mono_classes_init:
10076 * Initialize the resources used by this module.
10079 mono_classes_init (void)
10081 mono_os_mutex_init (&classes_mutex);
10083 mono_native_tls_alloc (&setup_fields_tls_id, NULL);
10084 mono_native_tls_alloc (&init_pending_tls_id, NULL);
10086 mono_counters_register ("MonoClassDef count",
10087 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_def_count);
10088 mono_counters_register ("MonoClassGtd count",
10089 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gtd_count);
10090 mono_counters_register ("MonoClassGenericInst count",
10091 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ginst_count);
10092 mono_counters_register ("MonoClassGenericParam count",
10093 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gparam_count);
10094 mono_counters_register ("MonoClassArray count",
10095 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_array_count);
10096 mono_counters_register ("MonoClassPointer count",
10097 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_pointer_count);
10098 mono_counters_register ("Inflated methods size",
10099 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
10100 mono_counters_register ("Inflated classes size",
10101 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
10102 mono_counters_register ("MonoClass size",
10103 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
10104 mono_counters_register ("MonoClassExt size",
10105 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
10107 mono_counters_register ("MonoClassExt count",
10108 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_count);
10112 * mono_classes_cleanup:
10114 * Free the resources used by this module.
10117 mono_classes_cleanup (void)
10119 mono_native_tls_free (setup_fields_tls_id);
10120 mono_native_tls_free (init_pending_tls_id);
10122 if (global_interface_bitset)
10123 mono_bitset_free (global_interface_bitset);
10124 global_interface_bitset = NULL;
10125 mono_os_mutex_destroy (&classes_mutex);
10129 * mono_class_get_exception_for_failure:
10130 * @klass: class in which the failure was detected
10132 * Return a constructed MonoException than the caller can then throw
10133 * using mono_raise_exception - or NULL if no failure is present (or
10134 * doesn't result in an exception).
10137 mono_class_get_exception_for_failure (MonoClass *klass)
10139 if (!mono_class_has_failure (klass))
10141 MonoError unboxed_error;
10142 mono_error_init (&unboxed_error);
10143 mono_error_set_for_class_failure (&unboxed_error, klass);
10144 return mono_error_convert_to_exception (&unboxed_error);
10148 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
10150 outer_klass = mono_class_get_generic_type_definition (outer_klass);
10151 inner_klass = mono_class_get_generic_type_definition (inner_klass);
10153 if (outer_klass == inner_klass)
10155 inner_klass = inner_klass->nested_in;
10156 } while (inner_klass);
10161 mono_class_get_generic_type_definition (MonoClass *klass)
10163 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
10164 return gklass ? gklass->container_class : klass;
10168 * Check if @klass is a subtype of @parent ignoring generic instantiations.
10170 * Generic instantiations are ignored for all super types of @klass.
10172 * Visibility checks ignoring generic instantiations.
10175 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
10178 klass = mono_class_get_generic_type_definition (klass);
10179 parent = mono_class_get_generic_type_definition (parent);
10180 mono_class_setup_supertypes (klass);
10182 for (i = 0; i < klass->idepth; ++i) {
10183 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
10189 * Subtype can only access parent members with family protection if the site object
10190 * is subclass of Subtype. For example:
10191 * class A { protected int x; }
10193 * void valid_access () {
10197 * void invalid_access () {
10204 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
10206 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
10209 if (context_klass == NULL)
10211 /*if access_klass is not member_klass context_klass must be type compat*/
10212 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10218 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10221 if (accessing == accessed)
10223 if (!accessed || !accessing)
10226 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10227 * anywhere so untrusted friends are not safe to access platform's code internals */
10228 if (mono_security_core_clr_enabled ()) {
10229 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10233 mono_assembly_load_friends (accessed);
10234 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10235 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10236 /* Be conservative with checks */
10237 if (!friend_->name)
10239 if (strcmp (accessing->aname.name, friend_->name))
10241 if (friend_->public_key_token [0]) {
10242 if (!accessing->aname.public_key_token [0])
10244 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10253 * If klass is a generic type or if it is derived from a generic type, return the
10254 * MonoClass of the generic definition
10255 * Returns NULL if not found
10258 get_generic_definition_class (MonoClass *klass)
10261 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
10262 if (gklass && gklass->container_class)
10263 return gklass->container_class;
10264 klass = klass->parent;
10270 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10273 for (i = 0; i < ginst->type_argc; ++i) {
10274 MonoType *type = ginst->type_argv[i];
10275 switch (type->type) {
10276 case MONO_TYPE_SZARRAY:
10277 if (!can_access_type (access_klass, type->data.klass))
10280 case MONO_TYPE_ARRAY:
10281 if (!can_access_type (access_klass, type->data.array->eklass))
10284 case MONO_TYPE_PTR:
10285 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10288 case MONO_TYPE_CLASS:
10289 case MONO_TYPE_VALUETYPE:
10290 case MONO_TYPE_GENERICINST:
10291 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10301 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10305 if (access_klass == member_klass)
10308 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10311 if (access_klass->element_class && !access_klass->enumtype)
10312 access_klass = access_klass->element_class;
10314 if (member_klass->element_class && !member_klass->enumtype)
10315 member_klass = member_klass->element_class;
10317 access_level = mono_class_get_flags (member_klass) & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10319 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10322 if (mono_class_is_ginst (member_klass) && !can_access_instantiation (access_klass, mono_class_get_generic_class (member_klass)->context.class_inst))
10325 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10328 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10331 /*Non nested type with nested visibility. We just fail it.*/
10332 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10335 switch (access_level) {
10336 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10337 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10339 case TYPE_ATTRIBUTE_PUBLIC:
10342 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10345 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10346 return is_nesting_type (member_klass, access_klass);
10348 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10349 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10351 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10352 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10354 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10355 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10356 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10358 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10359 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10360 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10365 /* FIXME: check visibility of type, too */
10367 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10369 MonoClass *member_generic_def;
10370 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10373 MonoGenericClass *access_gklass = mono_class_try_get_generic_class (access_klass);
10374 if (((access_gklass && access_gklass->container_class) ||
10375 mono_class_is_gtd (access_klass)) &&
10376 (member_generic_def = get_generic_definition_class (member_klass))) {
10377 MonoClass *access_container;
10379 if (mono_class_is_gtd (access_klass))
10380 access_container = access_klass;
10382 access_container = access_gklass->container_class;
10384 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10388 /* Partition I 8.5.3.2 */
10389 /* the access level values are the same for fields and methods */
10390 switch (access_level) {
10391 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10392 /* same compilation unit */
10393 return access_klass->image == member_klass->image;
10394 case FIELD_ATTRIBUTE_PRIVATE:
10395 return access_klass == member_klass;
10396 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10397 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10398 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10401 case FIELD_ATTRIBUTE_ASSEMBLY:
10402 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10403 case FIELD_ATTRIBUTE_FAMILY:
10404 if (is_valid_family_access (access_klass, member_klass, context_klass))
10407 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10408 if (is_valid_family_access (access_klass, member_klass, context_klass))
10410 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10411 case FIELD_ATTRIBUTE_PUBLIC:
10418 * mono_method_can_access_field:
10419 * @method: Method that will attempt to access the field
10420 * @field: the field to access
10422 * Used to determine if a method is allowed to access the specified field.
10424 * Returns: TRUE if the given @method is allowed to access the @field while following
10425 * the accessibility rules of the CLI.
10428 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10430 /* FIXME: check all overlapping fields */
10431 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10433 MonoClass *nested = method->klass->nested_in;
10435 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10438 nested = nested->nested_in;
10445 * mono_method_can_access_method:
10446 * @method: Method that will attempt to access the other method
10447 * @called: the method that we want to probe for accessibility.
10449 * Used to determine if the @method is allowed to access the specified @called method.
10451 * Returns: TRUE if the given @method is allowed to invoke the @called while following
10452 * the accessibility rules of the CLI.
10455 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10457 method = mono_method_get_method_definition (method);
10458 called = mono_method_get_method_definition (called);
10459 return mono_method_can_access_method_full (method, called, NULL);
10463 * mono_method_can_access_method_full:
10464 * @method: The caller method
10465 * @called: The called method
10466 * @context_klass: The static type on stack of the owner @called object used
10468 * This function must be used with instance calls, as they have more strict family accessibility.
10469 * It can be used with static methods, but context_klass should be NULL.
10471 * Returns: TRUE if caller have proper visibility and acessibility to @called
10474 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10476 /* Wrappers are except from access checks */
10477 if (method->wrapper_type != MONO_WRAPPER_NONE || called->wrapper_type != MONO_WRAPPER_NONE)
10480 MonoClass *access_class = method->klass;
10481 MonoClass *member_class = called->klass;
10482 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10484 MonoClass *nested = access_class->nested_in;
10486 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10489 nested = nested->nested_in;
10496 can = can_access_type (access_class, member_class);
10498 MonoClass *nested = access_class->nested_in;
10500 can = can_access_type (nested, member_class);
10503 nested = nested->nested_in;
10510 if (called->is_inflated) {
10511 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10512 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10521 * mono_method_can_access_field_full:
10522 * @method: The caller method
10523 * @field: The accessed field
10524 * @context_klass: The static type on stack of the owner @field object used
10526 * This function must be used with instance fields, as they have more strict family accessibility.
10527 * It can be used with static fields, but context_klass should be NULL.
10529 * Returns: TRUE if caller have proper visibility and acessibility to @field
10532 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10534 MonoClass *access_class = method->klass;
10535 MonoClass *member_class = field->parent;
10536 /* FIXME: check all overlapping fields */
10537 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10539 MonoClass *nested = access_class->nested_in;
10541 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10544 nested = nested->nested_in;
10551 can = can_access_type (access_class, member_class);
10553 MonoClass *nested = access_class->nested_in;
10555 can = can_access_type (nested, member_class);
10558 nested = nested->nested_in;
10568 * mono_class_can_access_class:
10569 * @source_class: The source class
10570 * @target_class: The accessed class
10572 * This function returns is @target_class is visible to @source_class
10574 * Returns: TRUE if source have proper visibility and acessibility to target
10577 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10579 return can_access_type (source_class, target_class);
10583 * mono_type_is_valid_enum_basetype:
10584 * @type: The MonoType to check
10586 * Returns: TRUE if the type can be used as the basetype of an enum
10588 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10589 switch (type->type) {
10592 case MONO_TYPE_BOOLEAN:
10595 case MONO_TYPE_CHAR:
10609 * mono_class_is_valid_enum:
10610 * @klass: An enum class to be validated
10612 * This method verify the required properties an enum should have.
10614 * Returns: TRUE if the informed enum class is valid
10616 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10617 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10618 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10621 mono_class_is_valid_enum (MonoClass *klass)
10623 MonoClassField * field;
10624 gpointer iter = NULL;
10625 gboolean found_base_field = FALSE;
10627 g_assert (klass->enumtype);
10628 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10629 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10633 if (!mono_class_is_auto_layout (klass))
10636 while ((field = mono_class_get_fields (klass, &iter))) {
10637 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10638 if (found_base_field)
10640 found_base_field = TRUE;
10641 if (!mono_type_is_valid_enum_basetype (field->type))
10646 if (!found_base_field)
10649 if (mono_class_get_method_count (klass) > 0)
10656 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10658 return gklass->context.class_inst == mono_class_get_generic_container (gklass->container_class)->context.class_inst;
10662 * mono_class_setup_interface_id:
10664 * Initializes MonoClass::interface_id if required.
10666 * LOCKING: Acquires the loader lock.
10669 mono_class_setup_interface_id (MonoClass *klass)
10671 mono_loader_lock ();
10672 if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10673 klass->interface_id = mono_get_unique_iid (klass);
10674 mono_loader_unlock ();
10678 * mono_class_alloc_ext:
10680 * Allocate klass->ext if not already done.
10683 mono_class_alloc_ext (MonoClass *klass)
10687 if (mono_class_get_ext (klass))
10690 ext = (MonoClassExt *)mono_class_alloc0 (klass, sizeof (MonoClassExt));
10691 mono_image_lock (klass->image);
10692 mono_memory_barrier ();
10693 if (!mono_class_get_ext (klass))
10694 mono_class_set_ext (klass, ext);
10695 class_ext_size += sizeof (MonoClassExt);
10697 mono_image_unlock (klass->image);
10701 * mono_class_setup_interfaces:
10703 * Initialize klass->interfaces/interfaces_count.
10704 * LOCKING: Acquires the loader lock.
10705 * This function can fail the type.
10708 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10710 int i, interface_count;
10711 MonoClass **interfaces;
10713 mono_error_init (error);
10715 if (klass->interfaces_inited)
10718 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10719 MonoType *args [1];
10721 /* generic IList, ICollection, IEnumerable */
10722 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10723 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10725 args [0] = &klass->element_class->byval_arg;
10726 interfaces [0] = mono_class_bind_generic_parameters (
10727 mono_defaults.generic_ilist_class, 1, args, FALSE);
10728 if (interface_count > 1)
10729 interfaces [1] = mono_class_bind_generic_parameters (
10730 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10731 } else if (mono_class_is_ginst (klass)) {
10732 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
10734 mono_class_setup_interfaces (gklass, error);
10735 if (!mono_error_ok (error)) {
10736 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10740 interface_count = gklass->interface_count;
10741 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10742 for (i = 0; i < interface_count; i++) {
10743 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (mono_class_get_generic_class (klass)), error);
10744 if (!mono_error_ok (error)) {
10745 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10750 interface_count = 0;
10754 mono_image_lock (klass->image);
10756 if (!klass->interfaces_inited) {
10757 klass->interface_count = interface_count;
10758 klass->interfaces = interfaces;
10760 mono_memory_barrier ();
10762 klass->interfaces_inited = TRUE;
10765 mono_image_unlock (klass->image);
10769 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10771 MonoClass *klass = field->parent;
10772 MonoImage *image = klass->image;
10773 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10775 int field_idx = field - klass->fields;
10777 mono_error_init (error);
10780 MonoClassField *gfield = >d->fields [field_idx];
10781 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10782 if (!mono_error_ok (error)) {
10783 char *full_name = mono_type_get_full_name (gtd);
10784 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));
10785 g_free (full_name);
10788 ftype = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10789 if (!mono_error_ok (error)) {
10790 char *full_name = mono_type_get_full_name (klass);
10791 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));
10792 g_free (full_name);
10796 guint32 cols [MONO_FIELD_SIZE];
10797 MonoGenericContainer *container = NULL;
10798 int idx = mono_class_get_first_field_idx (klass) + field_idx;
10800 /*FIXME, in theory we do not lazy load SRE fields*/
10801 g_assert (!image_is_dynamic (image));
10803 if (mono_class_is_gtd (klass)) {
10804 container = mono_class_get_generic_container (klass);
10806 container = mono_class_get_generic_container (gtd);
10807 g_assert (container);
10810 /* first_field_idx and idx points into the fieldptr table */
10811 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10813 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10814 char *full_name = mono_type_get_full_name (klass);
10815 mono_error_set_type_load_class (error, klass, "Could not verify field '%s:%s' signature", full_name, field->name);;
10816 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
10817 g_free (full_name);
10821 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10823 mono_metadata_decode_value (sig, &sig);
10824 /* FIELD signature == 0x06 */
10825 g_assert (*sig == 0x06);
10827 ftype = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10829 char *full_name = mono_type_get_full_name (klass);
10830 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));
10831 g_free (full_name);
10834 mono_memory_barrier ();
10835 field->type = ftype;
10839 mono_field_resolve_flags (MonoClassField *field)
10841 MonoClass *klass = field->parent;
10842 MonoImage *image = klass->image;
10843 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10844 int field_idx = field - klass->fields;
10848 MonoClassField *gfield = >d->fields [field_idx];
10849 return mono_field_get_flags (gfield);
10851 int idx = mono_class_get_first_field_idx (klass) + field_idx;
10853 /*FIXME, in theory we do not lazy load SRE fields*/
10854 g_assert (!image_is_dynamic (image));
10856 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10861 * mono_class_get_fields_lazy:
10862 * @klass: the MonoClass to act on
10864 * This routine is an iterator routine for retrieving the fields in a class.
10865 * Only minimal information about fields are loaded. Accessors must be used
10866 * for all MonoClassField returned.
10868 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10869 * iterate over all of the elements. When no more values are
10870 * available, the return value is NULL.
10872 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10875 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10877 MonoClassField* field;
10881 mono_class_setup_basic_field_info (klass);
10882 if (!klass->fields)
10884 /* start from the first */
10885 if (mono_class_get_field_count (klass)) {
10886 *iter = &klass->fields [0];
10887 return (MonoClassField *)*iter;
10893 field = (MonoClassField *)*iter;
10895 if (field < &klass->fields [mono_class_get_field_count (klass)]) {
10897 return (MonoClassField *)*iter;
10903 mono_class_full_name (MonoClass *klass)
10905 return mono_type_full_name (&klass->byval_arg);
10908 /* Declare all shared lazy type lookup functions */
10909 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, System.Runtime.InteropServices, SafeHandle)