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_class_layout_fields (klass, instance_size, packing_size, FALSE);
1645 init_list = g_slist_remove (init_list, klass);
1646 mono_native_tls_set_value (setup_fields_tls_id, init_list);
1650 init_sizes_with_info (MonoClass *klass, MonoCachedClassInfo *cached_info)
1653 klass->instance_size = cached_info->instance_size;
1654 klass->sizes.class_size = cached_info->class_size;
1655 klass->packing_size = cached_info->packing_size;
1656 klass->min_align = cached_info->min_align;
1657 klass->blittable = cached_info->blittable;
1658 klass->has_references = cached_info->has_references;
1659 klass->has_static_refs = cached_info->has_static_refs;
1660 klass->no_special_static_fields = cached_info->no_special_static_fields;
1663 if (!klass->size_inited)
1664 mono_class_setup_fields (klass);
1669 * mono_class_init_sizes:
1671 * Initializes the size related fields of @klass without loading all field data if possible.
1672 * Sets the following fields in @klass:
1674 * - sizes.class_size
1681 * Can fail the class.
1683 * LOCKING: Acquires the loader lock.
1686 mono_class_init_sizes (MonoClass *klass)
1688 MonoCachedClassInfo cached_info;
1689 gboolean has_cached_info;
1691 if (klass->size_inited)
1694 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
1696 init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
1700 * mono_type_get_basic_type_from_generic:
1703 * Returns a closed type corresponding to the possibly open type
1707 mono_type_get_basic_type_from_generic (MonoType *type)
1709 /* When we do generic sharing we let type variables stand for reference/primitive types. */
1710 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) &&
1711 (!type->data.generic_param->gshared_constraint || type->data.generic_param->gshared_constraint->type == MONO_TYPE_OBJECT))
1712 return &mono_defaults.object_class->byval_arg;
1717 class_has_references (MonoClass *klass)
1719 mono_class_init_sizes (klass);
1722 * has_references is not set if this is called recursively, but this is not a problem since this is only used
1723 * during field layout, and instance fields are initialized before static fields, and instance fields can't
1726 return klass->has_references;
1730 type_has_references (MonoClass *klass, MonoType *ftype)
1732 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (klass, ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && class_has_references (mono_class_from_mono_type (ftype)))))
1734 if (!ftype->byref && (ftype->type == MONO_TYPE_VAR || ftype->type == MONO_TYPE_MVAR)) {
1735 MonoGenericParam *gparam = ftype->data.generic_param;
1737 if (gparam->gshared_constraint)
1738 return class_has_references (mono_class_from_mono_type (gparam->gshared_constraint));
1744 * mono_class_layout_fields:
1746 * @base_instance_size: base instance size
1749 * This contains the common code for computing the layout of classes and sizes.
1750 * This should only be called from mono_class_setup_fields () and
1751 * typebuilder_setup_fields ().
1753 * LOCKING: Acquires the loader lock
1756 mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_size, gboolean sre)
1759 const int top = mono_class_get_field_count (klass);
1760 guint32 layout = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK;
1761 guint32 pass, passes, real_size;
1762 gboolean gc_aware_layout = FALSE;
1763 gboolean has_static_fields = FALSE;
1764 gboolean has_references = FALSE;
1765 gboolean has_static_refs = FALSE;
1766 MonoClassField *field;
1768 int instance_size = base_instance_size;
1769 int class_size, min_align;
1773 * We want to avoid doing complicated work inside locks, so we compute all the required
1774 * information and write it to @klass inside a lock.
1776 if (klass->fields_inited)
1779 if ((packing_size & 0xffffff00) != 0) {
1780 mono_class_set_type_load_failure (klass, "Could not load struct '%s' with packing size %d >= 256", klass->name, packing_size);
1784 if (klass->parent) {
1785 min_align = klass->parent->min_align;
1786 /* we use | since it may have been set already */
1787 has_references = klass->has_references | klass->parent->has_references;
1791 /* We can't really enable 16 bytes alignment until the GC supports it.
1792 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1793 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1794 Bug #506144 is an example of this issue.
1796 if (klass->simd_type)
1801 * When we do generic sharing we need to have layout
1802 * information for open generic classes (either with a generic
1803 * context containing type variables or with a generic
1804 * container), so we don't return in that case anymore.
1807 if (klass->enumtype) {
1808 for (i = 0; i < top; i++) {
1809 field = &klass->fields [i];
1810 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1811 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
1816 if (!mono_class_enum_basetype (klass)) {
1817 mono_class_set_type_load_failure (klass, "The enumeration's base type is invalid.");
1823 * Enable GC aware auto layout: in this mode, reference
1824 * fields are grouped together inside objects, increasing collector
1826 * Requires that all classes whose layout is known to native code be annotated
1827 * with [StructLayout (LayoutKind.Sequential)]
1828 * Value types have gc_aware_layout disabled by default, as per
1829 * what the default is for other runtimes.
1831 /* corlib is missing [StructLayout] directives in many places */
1832 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1833 if (!klass->valuetype)
1834 gc_aware_layout = TRUE;
1837 /* Compute klass->blittable */
1840 blittable = klass->parent->blittable;
1841 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(mono_is_corlib_image (klass->image) && !strcmp (klass->name_space, "System") && !strcmp (klass->name, "ValueType")) && top)
1843 for (i = 0; i < top; i++) {
1844 field = &klass->fields [i];
1846 if (mono_field_is_deleted (field))
1848 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1851 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1854 MonoClass *field_class = mono_class_from_mono_type (field->type);
1856 mono_class_setup_fields (field_class);
1857 if (mono_class_has_failure (field_class)) {
1858 MonoError field_error;
1859 mono_error_init (&field_error);
1860 mono_error_set_for_class_failure (&field_error, field_class);
1861 mono_class_set_type_load_failure (klass, "Could not set up field '%s' due to: %s", field->name, mono_error_get_message (&field_error));
1862 mono_error_cleanup (&field_error);
1866 if (!field_class || !field_class->blittable)
1870 if (klass->enumtype)
1871 blittable = klass->element_class->blittable;
1873 if (mono_class_has_failure (klass))
1875 if (klass == mono_defaults.string_class)
1878 /* Compute klass->has_references */
1880 * Process non-static fields first, since static fields might recursively
1881 * refer to the class itself.
1883 for (i = 0; i < top; i++) {
1886 field = &klass->fields [i];
1888 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1889 ftype = mono_type_get_underlying_type (field->type);
1890 ftype = mono_type_get_basic_type_from_generic (ftype);
1891 if (type_has_references (klass, ftype))
1892 has_references = TRUE;
1897 * Compute field layout and total size (not considering static fields)
1899 field_offsets = g_new0 (int, top);
1900 int first_field_idx = mono_class_has_static_metadata (klass) ? mono_class_get_first_field_idx (klass) : 0;
1902 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1903 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1904 if (gc_aware_layout)
1909 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1912 if (klass->parent) {
1913 mono_class_setup_fields (klass->parent);
1914 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Cannot initialize parent class"))
1916 real_size = klass->parent->instance_size;
1918 real_size = sizeof (MonoObject);
1921 for (pass = 0; pass < passes; ++pass) {
1922 for (i = 0; i < top; i++){
1927 field = &klass->fields [i];
1929 if (mono_field_is_deleted (field))
1931 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1934 ftype = mono_type_get_underlying_type (field->type);
1935 ftype = mono_type_get_basic_type_from_generic (ftype);
1936 if (gc_aware_layout) {
1937 if (type_has_references (klass, ftype)) {
1946 if ((top == 1) && (instance_size == sizeof (MonoObject)) &&
1947 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1948 /* This field is a hack inserted by MCS to empty structures */
1952 size = mono_type_size (field->type, &align);
1954 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1955 align = packing_size ? MIN (packing_size, align): align;
1956 /* if the field has managed references, we need to force-align it
1959 if (type_has_references (klass, ftype))
1960 align = MAX (align, sizeof (gpointer));
1962 min_align = MAX (align, min_align);
1963 field_offsets [i] = real_size;
1965 field_offsets [i] += align - 1;
1966 field_offsets [i] &= ~(align - 1);
1968 /*TypeBuilders produce all sort of weird things*/
1969 g_assert (image_is_dynamic (klass->image) || field_offsets [i] > 0);
1970 real_size = field_offsets [i] + size;
1973 /* Make SIMD types as big as a SIMD register since they can be stored into using simd stores */
1974 if (klass->simd_type)
1975 real_size = MAX (real_size, sizeof (MonoObject) + 16);
1976 instance_size = MAX (real_size, instance_size);
1978 if (instance_size & (min_align - 1)) {
1979 instance_size += min_align - 1;
1980 instance_size &= ~(min_align - 1);
1984 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
1988 for (i = 0; i < top; i++) {
1993 field = &klass->fields [i];
1996 * There must be info about all the fields in a type if it
1997 * uses explicit layout.
1999 if (mono_field_is_deleted (field))
2001 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2004 size = mono_type_size (field->type, &align);
2005 align = packing_size ? MIN (packing_size, align): align;
2006 min_align = MAX (align, min_align);
2009 /* Already set by typebuilder_setup_fields () */
2010 field_offsets [i] = field->offset + sizeof (MonoObject);
2012 int idx = first_field_idx + i;
2014 mono_metadata_field_info (klass->image, idx, &offset, NULL, NULL);
2015 field_offsets [i] = offset + sizeof (MonoObject);
2017 ftype = mono_type_get_underlying_type (field->type);
2018 ftype = mono_type_get_basic_type_from_generic (ftype);
2019 if (type_has_references (klass, ftype)) {
2020 if (field_offsets [i] % sizeof (gpointer)) {
2021 mono_class_set_type_load_failure (klass, "Reference typed field '%s' has explicit offset that is not pointer-size aligned.", field->name);
2028 real_size = MAX (real_size, size + field_offsets [i]);
2031 if (klass->has_references) {
2032 ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
2034 /* Check for overlapping reference and non-reference fields */
2035 for (i = 0; i < top; i++) {
2038 field = &klass->fields [i];
2040 if (mono_field_is_deleted (field))
2042 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2044 ftype = mono_type_get_underlying_type (field->type);
2045 if (MONO_TYPE_IS_REFERENCE (ftype))
2046 ref_bitmap [field_offsets [i] / sizeof (gpointer)] = 1;
2048 for (i = 0; i < top; i++) {
2049 field = &klass->fields [i];
2051 if (mono_field_is_deleted (field))
2053 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2056 // FIXME: Too much code does this
2058 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field_offsets [i] / sizeof (gpointer)]) {
2059 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]);
2063 g_free (ref_bitmap);
2066 instance_size = MAX (real_size, instance_size);
2067 if (instance_size & (min_align - 1)) {
2068 instance_size += min_align - 1;
2069 instance_size &= ~(min_align - 1);
2075 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2077 * This leads to all kinds of problems with nested structs, so only
2078 * enable it when a MONO_DEBUG property is set.
2080 * For small structs, set min_align to at least the struct size to improve
2081 * performance, and since the JIT memset/memcpy code assumes this and generates
2082 * unaligned accesses otherwise. See #78990 for a testcase.
2084 if (mono_align_small_structs && top) {
2085 if (instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2086 min_align = MAX (min_align, instance_size - sizeof (MonoObject));
2090 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR)
2091 instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
2092 else if (klass->byval_arg.type == MONO_TYPE_PTR)
2093 instance_size = sizeof (MonoObject) + sizeof (gpointer);
2095 /* Publish the data */
2096 mono_loader_lock ();
2097 if (klass->instance_size && !klass->image->dynamic) {
2098 /* Might be already set using cached info */
2099 if (klass->instance_size != instance_size) {
2100 /* Emit info to help debugging */
2101 g_print ("%s %s\n", klass->name_space, klass->name);
2102 g_print ("%d %d %d %d\n", klass->instance_size, instance_size, klass->blittable, blittable);
2103 g_print ("%d %d %d %d\n", klass->has_references, has_references, klass->packing_size, packing_size);
2104 g_print ("%d %d\n", klass->min_align, min_align);
2105 for (i = 0; i < top; ++i) {
2106 field = &klass->fields [i];
2107 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
2108 printf (" %s %d %d\n", klass->fields [i].name, klass->fields [i].offset, field_offsets [i]);
2111 g_assert (klass->instance_size == instance_size);
2113 klass->instance_size = instance_size;
2115 klass->blittable = blittable;
2116 klass->has_references = has_references;
2117 klass->packing_size = packing_size;
2118 klass->min_align = min_align;
2119 for (i = 0; i < top; ++i) {
2120 field = &klass->fields [i];
2121 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
2122 klass->fields [i].offset = field_offsets [i];
2125 mono_memory_barrier ();
2126 klass->size_inited = 1;
2127 mono_loader_unlock ();
2130 * Compute static field layout and size
2131 * Static fields can reference the class itself, so this has to be
2132 * done after instance_size etc. are initialized.
2135 for (i = 0; i < top; i++) {
2139 field = &klass->fields [i];
2141 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2143 if (mono_field_is_deleted (field))
2146 if (mono_type_has_exceptions (field->type)) {
2147 mono_class_set_type_load_failure (klass, "Field '%s' has an invalid type.", field->name);
2151 has_static_fields = TRUE;
2153 size = mono_type_size (field->type, &align);
2154 field_offsets [i] = class_size;
2155 /*align is always non-zero here*/
2156 field_offsets [i] += align - 1;
2157 field_offsets [i] &= ~(align - 1);
2158 class_size = field_offsets [i] + size;
2161 if (has_static_fields && class_size == 0)
2162 /* Simplify code which depends on class_size != 0 if the class has static fields */
2165 /* Compute klass->has_static_refs */
2166 has_static_refs = FALSE;
2167 for (i = 0; i < top; i++) {
2170 field = &klass->fields [i];
2172 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
2173 ftype = mono_type_get_underlying_type (field->type);
2174 ftype = mono_type_get_basic_type_from_generic (ftype);
2175 if (type_has_references (klass, ftype))
2176 has_static_refs = TRUE;
2180 /*valuetypes can't be neither bigger than 1Mb or empty. */
2181 if (klass->valuetype && (klass->instance_size <= 0 || klass->instance_size > (0x100000 + sizeof (MonoObject))))
2182 mono_class_set_type_load_failure (klass, "Value type instance size (%d) cannot be zero, negative, or bigger than 1Mb", klass->instance_size);
2184 /* Publish the data */
2185 mono_loader_lock ();
2187 klass->sizes.class_size = class_size;
2188 klass->has_static_refs = has_static_refs;
2189 for (i = 0; i < top; ++i) {
2190 field = &klass->fields [i];
2192 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2193 field->offset = field_offsets [i];
2196 mono_memory_barrier ();
2197 klass->fields_inited = 1;
2198 mono_loader_unlock ();
2200 g_free (field_offsets);
2204 create_array_method (MonoClass *klass, const char *name, MonoMethodSignature *sig)
2208 method = (MonoMethod *) mono_image_alloc0 (klass->image, sizeof (MonoMethodPInvoke));
2209 method->klass = klass;
2210 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2211 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2212 method->signature = sig;
2213 method->name = name;
2216 if (name [0] == '.') {
2217 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2219 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2225 * mono_class_setup_methods:
2228 * Initializes the 'methods' array in CLASS.
2229 * Calling this method should be avoided if possible since it allocates a lot
2230 * of long-living MonoMethod structures.
2231 * Methods belonging to an interface are assigned a sequential slot starting
2234 * On failure this function sets klass->has_failure and stores a MonoErrorBoxed with details
2237 mono_class_setup_methods (MonoClass *klass)
2240 MonoMethod **methods;
2245 if (mono_class_is_ginst (klass)) {
2247 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2249 mono_class_init (gklass);
2250 if (!mono_class_has_failure (gklass))
2251 mono_class_setup_methods (gklass);
2252 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2255 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2256 count = mono_class_get_method_count (gklass);
2257 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * (count + 1));
2259 for (i = 0; i < count; i++) {
2260 methods [i] = mono_class_inflate_generic_method_full_checked (
2261 gklass->methods [i], klass, mono_class_get_context (klass), &error);
2262 if (!mono_error_ok (&error)) {
2263 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2264 mono_class_set_type_load_failure (klass, "Could not inflate method %s due to %s", method, mono_error_get_message (&error));
2267 mono_error_cleanup (&error);
2271 } else if (klass->rank) {
2273 MonoMethod *amethod;
2274 MonoMethodSignature *sig;
2275 int count_generic = 0, first_generic = 0;
2277 gboolean jagged_ctor = FALSE;
2279 count = 3 + (klass->rank > 1? 2: 1);
2281 mono_class_setup_interfaces (klass, &error);
2282 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2284 if (klass->rank == 1 && klass->element_class->rank) {
2289 if (klass->interface_count) {
2290 count_generic = generic_array_methods (klass);
2291 first_generic = count;
2292 count += klass->interface_count * count_generic;
2295 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * count);
2297 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2298 sig->ret = &mono_defaults.void_class->byval_arg;
2299 sig->pinvoke = TRUE;
2300 sig->hasthis = TRUE;
2301 for (i = 0; i < klass->rank; ++i)
2302 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2304 amethod = create_array_method (klass, ".ctor", sig);
2305 methods [method_num++] = amethod;
2306 if (klass->rank > 1) {
2307 sig = mono_metadata_signature_alloc (klass->image, klass->rank * 2);
2308 sig->ret = &mono_defaults.void_class->byval_arg;
2309 sig->pinvoke = TRUE;
2310 sig->hasthis = TRUE;
2311 for (i = 0; i < klass->rank * 2; ++i)
2312 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2314 amethod = create_array_method (klass, ".ctor", sig);
2315 methods [method_num++] = amethod;
2319 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2320 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2321 sig->ret = &mono_defaults.void_class->byval_arg;
2322 sig->pinvoke = TRUE;
2323 sig->hasthis = TRUE;
2324 for (i = 0; i < klass->rank + 1; ++i)
2325 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2326 amethod = create_array_method (klass, ".ctor", sig);
2327 methods [method_num++] = amethod;
2330 /* element Get (idx11, [idx2, ...]) */
2331 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2332 sig->ret = &klass->element_class->byval_arg;
2333 sig->pinvoke = TRUE;
2334 sig->hasthis = TRUE;
2335 for (i = 0; i < klass->rank; ++i)
2336 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2337 amethod = create_array_method (klass, "Get", sig);
2338 methods [method_num++] = amethod;
2339 /* element& Address (idx11, [idx2, ...]) */
2340 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2341 sig->ret = &klass->element_class->this_arg;
2342 sig->pinvoke = TRUE;
2343 sig->hasthis = TRUE;
2344 for (i = 0; i < klass->rank; ++i)
2345 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2346 amethod = create_array_method (klass, "Address", sig);
2347 methods [method_num++] = amethod;
2348 /* void Set (idx11, [idx2, ...], element) */
2349 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2350 sig->ret = &mono_defaults.void_class->byval_arg;
2351 sig->pinvoke = TRUE;
2352 sig->hasthis = TRUE;
2353 for (i = 0; i < klass->rank; ++i)
2354 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2355 sig->params [i] = &klass->element_class->byval_arg;
2356 amethod = create_array_method (klass, "Set", sig);
2357 methods [method_num++] = amethod;
2359 for (i = 0; i < klass->interface_count; i++)
2360 setup_generic_array_ifaces (klass, klass->interfaces [i], methods, first_generic + i * count_generic);
2361 } else if (mono_class_has_static_metadata (klass)) {
2363 int first_idx = mono_class_get_first_method_idx (klass);
2365 count = mono_class_get_method_count (klass);
2366 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * count);
2367 for (i = 0; i < count; ++i) {
2368 int idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_METHOD, first_idx + i + 1);
2369 methods [i] = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | idx, klass, NULL, &error);
2371 mono_class_set_type_load_failure (klass, "Could not load method %d due to %s", i, mono_error_get_message (&error));
2372 mono_error_cleanup (&error);
2376 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * 1);
2380 if (MONO_CLASS_IS_INTERFACE (klass)) {
2382 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2383 for (i = 0; i < count; ++i) {
2384 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2385 methods [i]->slot = slot++;
2389 mono_image_lock (klass->image);
2391 if (!klass->methods) {
2392 mono_class_set_method_count (klass, count);
2394 /* Needed because of the double-checking locking pattern */
2395 mono_memory_barrier ();
2397 klass->methods = methods;
2400 mono_image_unlock (klass->image);
2404 * mono_class_get_method_by_index:
2406 * Returns klass->methods [index], initializing klass->methods if neccesary.
2408 * LOCKING: Acquires the loader lock.
2411 mono_class_get_method_by_index (MonoClass *klass, int index)
2415 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
2416 /* Avoid calling setup_methods () if possible */
2417 if (gklass && !klass->methods) {
2420 m = mono_class_inflate_generic_method_full_checked (
2421 gklass->container_class->methods [index], klass, mono_class_get_context (klass), &error);
2422 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2424 * If setup_methods () is called later for this class, no duplicates are created,
2425 * since inflate_generic_method guarantees that only one instance of a method
2426 * is created for each context.
2429 mono_class_setup_methods (klass);
2430 g_assert (m == klass->methods [index]);
2434 mono_class_setup_methods (klass);
2435 if (mono_class_has_failure (klass)) /*FIXME do proper error handling*/
2437 g_assert (index >= 0 && index < mono_class_get_method_count (klass));
2438 return klass->methods [index];
2443 * mono_class_get_inflated_method:
2445 * Given an inflated class CLASS and a method METHOD which should be a method of
2446 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2449 mono_class_get_inflated_method (MonoClass *klass, MonoMethod *method)
2451 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2454 g_assert (method->klass == gklass);
2456 mono_class_setup_methods (gklass);
2457 g_assert (!mono_class_has_failure (gklass)); /*FIXME do proper error handling*/
2459 mcount = mono_class_get_method_count (gklass);
2460 for (i = 0; i < mcount; ++i) {
2461 if (gklass->methods [i] == method) {
2462 if (klass->methods) {
2463 return klass->methods [i];
2466 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], klass, mono_class_get_context (klass), &error);
2467 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2477 * mono_class_get_vtable_entry:
2479 * Returns klass->vtable [offset], computing it if neccesary. Returns NULL on failure.
2480 * LOCKING: Acquires the loader lock.
2483 mono_class_get_vtable_entry (MonoClass *klass, int offset)
2487 if (klass->rank == 1) {
2489 * szarrays do not overwrite any methods of Array, so we can avoid
2490 * initializing their vtables in some cases.
2492 mono_class_setup_vtable (klass->parent);
2493 if (offset < klass->parent->vtable_size)
2494 return klass->parent->vtable [offset];
2497 if (mono_class_is_ginst (klass)) {
2499 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2500 mono_class_setup_vtable (gklass);
2501 m = gklass->vtable [offset];
2503 m = mono_class_inflate_generic_method_full_checked (m, klass, mono_class_get_context (klass), &error);
2504 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2506 mono_class_setup_vtable (klass);
2507 if (mono_class_has_failure (klass))
2509 m = klass->vtable [offset];
2516 * mono_class_get_vtable_size:
2518 * Return the vtable size for KLASS.
2521 mono_class_get_vtable_size (MonoClass *klass)
2523 mono_class_setup_vtable (klass);
2525 return klass->vtable_size;
2529 * mono_class_setup_properties:
2531 * Initialize klass->ext.property and klass->ext.properties.
2533 * This method can fail the class.
2536 mono_class_setup_properties (MonoClass *klass)
2538 guint startm, endm, i, j;
2539 guint32 cols [MONO_PROPERTY_SIZE];
2540 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2541 MonoProperty *properties;
2545 MonoClassExt *ext = mono_class_get_ext (klass);
2546 if (ext && ext->properties)
2549 if (mono_class_is_ginst (klass)) {
2550 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2552 mono_class_init (gklass);
2553 mono_class_setup_properties (gklass);
2554 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2557 MonoClassExt *gext = mono_class_get_ext (gklass);
2558 properties = mono_class_new0 (klass, MonoProperty, gext->property.count + 1);
2560 for (i = 0; i < gext->property.count; i++) {
2562 MonoProperty *prop = &properties [i];
2564 *prop = gext->properties [i];
2567 prop->get = mono_class_inflate_generic_method_full_checked (
2568 prop->get, klass, mono_class_get_context (klass), &error);
2570 prop->set = mono_class_inflate_generic_method_full_checked (
2571 prop->set, klass, mono_class_get_context (klass), &error);
2573 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2574 prop->parent = klass;
2577 first = gext->property.first;
2578 count = gext->property.count;
2580 first = mono_metadata_properties_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2581 count = last - first;
2584 mono_class_setup_methods (klass);
2585 if (mono_class_has_failure (klass))
2589 properties = (MonoProperty *)mono_class_alloc0 (klass, sizeof (MonoProperty) * count);
2590 for (i = first; i < last; ++i) {
2591 mono_metadata_decode_table_row (klass->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2592 properties [i - first].parent = klass;
2593 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2594 properties [i - first].name = mono_metadata_string_heap (klass->image, cols [MONO_PROPERTY_NAME]);
2596 startm = mono_metadata_methods_from_property (klass->image, i, &endm);
2597 int first_idx = mono_class_get_first_method_idx (klass);
2598 for (j = startm; j < endm; ++j) {
2601 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2603 if (klass->image->uncompressed_metadata) {
2605 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2606 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2607 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2609 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - first_idx];
2612 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2613 case METHOD_SEMANTIC_SETTER:
2614 properties [i - first].set = method;
2616 case METHOD_SEMANTIC_GETTER:
2617 properties [i - first].get = method;
2626 mono_class_alloc_ext (klass);
2627 ext = mono_class_get_ext (klass);
2629 mono_image_lock (klass->image);
2631 if (ext->properties) {
2632 /* We leak 'properties' which was allocated from the image mempool */
2633 mono_image_unlock (klass->image);
2637 ext->property.first = first;
2638 ext->property.count = count;
2640 /* Flush any pending writes as we do double checked locking on klass->ext->properties */
2641 mono_memory_barrier ();
2643 /* Leave this assignment as the last op in the function */
2644 ext->properties = properties;
2646 mono_image_unlock (klass->image);
2650 inflate_method_listz (MonoMethod **methods, MonoClass *klass, MonoGenericContext *context)
2652 MonoMethod **om, **retval;
2655 for (om = methods, count = 0; *om; ++om, ++count)
2658 retval = g_new0 (MonoMethod*, count + 1);
2660 for (om = methods, count = 0; *om; ++om, ++count) {
2662 retval [count] = mono_class_inflate_generic_method_full_checked (*om, klass, context, &error);
2663 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2669 /*This method can fail the class.*/
2671 mono_class_setup_events (MonoClass *klass)
2674 guint startm, endm, i, j;
2675 guint32 cols [MONO_EVENT_SIZE];
2676 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2680 MonoClassExt *ext = mono_class_get_ext (klass);
2681 if (ext && ext->events)
2684 if (mono_class_is_ginst (klass)) {
2685 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2686 MonoGenericContext *context = NULL;
2688 mono_class_setup_events (gklass);
2689 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2692 MonoClassExt *gext = mono_class_get_ext (gklass);
2693 first = gext->event.first;
2694 count = gext->event.count;
2696 events = mono_class_new0 (klass, MonoEvent, count);
2699 context = mono_class_get_context (klass);
2701 for (i = 0; i < count; i++) {
2703 MonoEvent *event = &events [i];
2704 MonoEvent *gevent = &gext->events [i];
2706 mono_error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2708 event->parent = klass;
2709 event->name = gevent->name;
2710 event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, klass, context, &error) : NULL;
2711 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2712 event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, klass, context, &error) : NULL;
2713 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2714 event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, klass, context, &error) : NULL;
2715 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2717 #ifndef MONO_SMALL_CONFIG
2718 event->other = gevent->other ? inflate_method_listz (gevent->other, klass, context) : NULL;
2720 event->attrs = gevent->attrs;
2723 first = mono_metadata_events_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2724 count = last - first;
2727 mono_class_setup_methods (klass);
2728 if (mono_class_has_failure (klass)) {
2733 events = (MonoEvent *)mono_class_alloc0 (klass, sizeof (MonoEvent) * count);
2734 for (i = first; i < last; ++i) {
2735 MonoEvent *event = &events [i - first];
2737 mono_metadata_decode_table_row (klass->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2738 event->parent = klass;
2739 event->attrs = cols [MONO_EVENT_FLAGS];
2740 event->name = mono_metadata_string_heap (klass->image, cols [MONO_EVENT_NAME]);
2742 startm = mono_metadata_methods_from_event (klass->image, i, &endm);
2743 int first_idx = mono_class_get_first_method_idx (klass);
2744 for (j = startm; j < endm; ++j) {
2747 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2749 if (klass->image->uncompressed_metadata) {
2751 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2752 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2753 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2755 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - first_idx];
2758 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2759 case METHOD_SEMANTIC_ADD_ON:
2760 event->add = method;
2762 case METHOD_SEMANTIC_REMOVE_ON:
2763 event->remove = method;
2765 case METHOD_SEMANTIC_FIRE:
2766 event->raise = method;
2768 case METHOD_SEMANTIC_OTHER: {
2769 #ifndef MONO_SMALL_CONFIG
2772 if (event->other == NULL) {
2773 event->other = g_new0 (MonoMethod*, 2);
2775 while (event->other [n])
2777 event->other = (MonoMethod **)g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2779 event->other [n] = method;
2780 /* NULL terminated */
2781 event->other [n + 1] = NULL;
2792 mono_class_alloc_ext (klass);
2793 ext = mono_class_get_ext (klass);
2795 mono_image_lock (klass->image);
2798 mono_image_unlock (klass->image);
2802 ext->event.first = first;
2803 ext->event.count = count;
2805 /* Flush any pending writes as we do double checked locking on klass->ext.events */
2806 mono_memory_barrier ();
2808 /* Leave this assignment as the last op in the function */
2809 ext->events = events;
2811 mono_image_unlock (klass->image);
2815 * Global pool of interface IDs, represented as a bitset.
2816 * LOCKING: Protected by the classes lock.
2818 static MonoBitSet *global_interface_bitset = NULL;
2821 * mono_unload_interface_ids:
2822 * @bitset: bit set of interface IDs
2824 * When an image is unloaded, the interface IDs associated with
2825 * the image are put back in the global pool of IDs so the numbers
2829 mono_unload_interface_ids (MonoBitSet *bitset)
2832 mono_bitset_sub (global_interface_bitset, bitset);
2837 mono_unload_interface_id (MonoClass *klass)
2839 if (global_interface_bitset && klass->interface_id) {
2841 mono_bitset_clear (global_interface_bitset, klass->interface_id);
2847 * mono_get_unique_iid:
2850 * Assign a unique integer ID to the interface represented by @class.
2851 * The ID will positive and as small as possible.
2852 * LOCKING: Acquires the classes lock.
2853 * Returns: The new ID.
2856 mono_get_unique_iid (MonoClass *klass)
2860 g_assert (MONO_CLASS_IS_INTERFACE (klass));
2864 if (!global_interface_bitset) {
2865 global_interface_bitset = mono_bitset_new (128, 0);
2868 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2870 int old_size = mono_bitset_size (global_interface_bitset);
2871 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2872 mono_bitset_free (global_interface_bitset);
2873 global_interface_bitset = new_set;
2876 mono_bitset_set (global_interface_bitset, iid);
2877 /* set the bit also in the per-image set */
2878 if (!mono_class_is_ginst (klass)) {
2879 if (klass->image->interface_bitset) {
2880 if (iid >= mono_bitset_size (klass->image->interface_bitset)) {
2881 MonoBitSet *new_set = mono_bitset_clone (klass->image->interface_bitset, iid + 1);
2882 mono_bitset_free (klass->image->interface_bitset);
2883 klass->image->interface_bitset = new_set;
2886 klass->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2888 mono_bitset_set (klass->image->interface_bitset, iid);
2893 #ifndef MONO_SMALL_CONFIG
2894 if (mono_print_vtable) {
2896 char *type_name = mono_type_full_name (&klass->byval_arg);
2897 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
2898 if (gklass && !gklass->context.class_inst->is_open) {
2899 generic_id = gklass->context.class_inst->id;
2900 g_assert (generic_id != 0);
2904 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, klass->image->name, type_name, generic_id);
2909 /* I've confirmed iids safe past 16 bits, however bitset code uses a signed int while testing.
2910 * Once this changes, it should be safe for us to allow 2^32-1 interfaces, until then 2^31-2 is the max. */
2911 g_assert (iid < INT_MAX);
2916 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2921 mono_class_setup_interfaces (klass, error);
2922 return_if_nok (error);
2924 for (i = 0; i < klass->interface_count; i++) {
2925 ic = klass->interfaces [i];
2928 *res = g_ptr_array_new ();
2929 g_ptr_array_add (*res, ic);
2930 mono_class_init (ic);
2931 if (mono_class_has_failure (ic)) {
2932 mono_error_set_type_load_class (error, ic, "Error Loading class");
2936 collect_implemented_interfaces_aux (ic, res, error);
2937 return_if_nok (error);
2942 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2944 GPtrArray *res = NULL;
2946 collect_implemented_interfaces_aux (klass, &res, error);
2947 if (!mono_error_ok (error)) {
2949 g_ptr_array_free (res, TRUE);
2956 compare_interface_ids (const void *p_key, const void *p_element) {
2957 const MonoClass *key = (const MonoClass *)p_key;
2958 const MonoClass *element = *(const MonoClass **)p_element;
2960 return (key->interface_id - element->interface_id);
2963 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2965 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2966 MonoClass **result = (MonoClass **)mono_binary_search (
2968 klass->interfaces_packed,
2969 klass->interface_offsets_count,
2970 sizeof (MonoClass *),
2971 compare_interface_ids);
2973 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2980 * mono_class_interface_offset_with_variance:
2982 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2983 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2985 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2987 * FIXME figure out MS disambiguation rules and fix this function.
2990 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2991 int i = mono_class_interface_offset (klass, itf);
2992 *non_exact_match = FALSE;
2996 if (!mono_class_has_variant_generic_params (itf))
2999 for (i = 0; i < klass->interface_offsets_count; i++) {
3000 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
3001 *non_exact_match = TRUE;
3002 return klass->interface_offsets_packed [i];
3010 print_implemented_interfaces (MonoClass *klass) {
3013 GPtrArray *ifaces = NULL;
3015 int ancestor_level = 0;
3017 name = mono_type_get_full_name (klass);
3018 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
3021 for (i = 0; i < klass->interface_offsets_count; i++)
3022 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3023 klass->interfaces_packed [i]->interface_id,
3024 klass->interface_offsets_packed [i],
3025 mono_class_get_method_count (klass->interfaces_packed [i]),
3026 klass->interfaces_packed [i]->name_space,
3027 klass->interfaces_packed [i]->name );
3028 printf ("Interface flags: ");
3029 for (i = 0; i <= klass->max_interface_id; i++)
3030 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
3031 printf ("(%d,T)", i);
3033 printf ("(%d,F)", i);
3035 printf ("Dump interface flags:");
3036 #ifdef COMPRESSED_INTERFACE_BITMAP
3038 const uint8_t* p = klass->interface_bitmap;
3039 i = klass->max_interface_id;
3041 printf (" %d x 00 %02X", p [0], p [1]);
3047 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
3048 printf (" %02X", klass->interface_bitmap [i]);
3051 while (klass != NULL) {
3052 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
3053 ifaces = mono_class_get_implemented_interfaces (klass, &error);
3054 if (!mono_error_ok (&error)) {
3055 printf (" Type failed due to %s\n", mono_error_get_message (&error));
3056 mono_error_cleanup (&error);
3057 } else if (ifaces) {
3058 for (i = 0; i < ifaces->len; i++) {
3059 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3060 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
3061 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3063 mono_class_interface_offset (klass, ic),
3064 mono_class_get_method_count (ic),
3068 g_ptr_array_free (ifaces, TRUE);
3071 klass = klass->parent;
3076 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
3079 args [0] = &arg0->byval_arg;
3081 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
3085 array_class_get_if_rank (MonoClass *klass, guint rank)
3087 return rank ? mono_array_class_get (klass, rank) : klass;
3091 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
3093 valuetype_types [0] = eclass;
3094 if (eclass == mono_defaults.int16_class)
3095 valuetype_types [1] = mono_defaults.uint16_class;
3096 else if (eclass == mono_defaults.uint16_class)
3097 valuetype_types [1] = mono_defaults.int16_class;
3098 else if (eclass == mono_defaults.int32_class)
3099 valuetype_types [1] = mono_defaults.uint32_class;
3100 else if (eclass == mono_defaults.uint32_class)
3101 valuetype_types [1] = mono_defaults.int32_class;
3102 else if (eclass == mono_defaults.int64_class)
3103 valuetype_types [1] = mono_defaults.uint64_class;
3104 else if (eclass == mono_defaults.uint64_class)
3105 valuetype_types [1] = mono_defaults.int64_class;
3106 else if (eclass == mono_defaults.byte_class)
3107 valuetype_types [1] = mono_defaults.sbyte_class;
3108 else if (eclass == mono_defaults.sbyte_class)
3109 valuetype_types [1] = mono_defaults.byte_class;
3110 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
3111 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
3114 static GENERATE_GET_CLASS_WITH_CACHE (generic_icollection, System.Collections.Generic, ICollection`1)
3115 static GENERATE_GET_CLASS_WITH_CACHE (generic_ienumerable, System.Collections.Generic, IEnumerable`1)
3116 static GENERATE_GET_CLASS_WITH_CACHE (generic_ienumerator, System.Collections.Generic, IEnumerator`1)
3117 static GENERATE_GET_CLASS_WITH_CACHE (generic_ireadonlylist, System.Collections.Generic, IReadOnlyList`1)
3118 static GENERATE_GET_CLASS_WITH_CACHE (generic_ireadonlycollection, System.Collections.Generic, IReadOnlyCollection`1)
3120 /* this won't be needed once bug #325495 is completely fixed
3121 * though we'll need something similar to know which interfaces to allow
3122 * in arrays when they'll be lazyly created
3124 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
3125 * MS returns diferrent types based on which instance is called. For example:
3126 * object obj = new byte[10][];
3127 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
3128 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
3131 * Fixing this should kill quite some code, save some bits and improve compatibility.
3134 get_implicit_generic_array_interfaces (MonoClass *klass, int *num, int *is_enumerator)
3136 MonoClass *eclass = klass->element_class;
3137 MonoClass* generic_icollection_class;
3138 MonoClass* generic_ienumerable_class;
3139 MonoClass* generic_ienumerator_class;
3140 MonoClass* generic_ireadonlylist_class;
3141 MonoClass* generic_ireadonlycollection_class;
3142 MonoClass *valuetype_types[2] = { NULL, NULL };
3143 MonoClass **interfaces = NULL;
3144 int i, nifaces, interface_count, real_count, original_rank;
3146 gboolean internal_enumerator;
3147 gboolean eclass_is_valuetype;
3149 if (!mono_defaults.generic_ilist_class) {
3153 internal_enumerator = FALSE;
3154 eclass_is_valuetype = FALSE;
3155 original_rank = eclass->rank;
3156 if (klass->byval_arg.type != MONO_TYPE_SZARRAY) {
3157 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
3158 if (gklass && klass->nested_in == mono_defaults.array_class && strcmp (klass->name, "InternalEnumerator`1") == 0) {
3160 * For a Enumerator<T[]> we need to get the list of interfaces for T.
3162 eclass = mono_class_from_mono_type (gklass->context.class_inst->type_argv [0]);
3163 original_rank = eclass->rank;
3165 eclass = eclass->element_class;
3166 internal_enumerator = TRUE;
3167 *is_enumerator = TRUE;
3175 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
3176 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
3178 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
3180 generic_icollection_class = mono_class_get_generic_icollection_class ();
3181 generic_ienumerable_class = mono_class_get_generic_ienumerable_class ();
3182 generic_ienumerator_class = mono_class_get_generic_ienumerator_class ();
3183 generic_ireadonlylist_class = mono_class_get_generic_ireadonlylist_class ();
3184 generic_ireadonlycollection_class = mono_class_get_generic_ireadonlycollection_class ();
3186 mono_class_init (eclass);
3189 * Arrays in 2.0 need to implement a number of generic interfaces
3190 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
3191 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
3192 * We collect the types needed to build the
3193 * instantiations in interfaces at intervals of 3/5, because 3/5 are
3194 * the generic interfaces needed to implement.
3196 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
3197 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
3199 if (eclass->valuetype) {
3200 nifaces = generic_ireadonlylist_class ? 5 : 3;
3201 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
3203 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
3204 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
3205 if (internal_enumerator) {
3207 if (valuetype_types [1])
3211 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3212 interfaces [0] = valuetype_types [0];
3213 if (valuetype_types [1])
3214 interfaces [nifaces] = valuetype_types [1];
3216 eclass_is_valuetype = TRUE;
3219 int idepth = eclass->idepth;
3220 if (!internal_enumerator)
3222 nifaces = generic_ireadonlylist_class ? 2 : 3;
3224 // FIXME: This doesn't seem to work/required for generic params
3225 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
3226 mono_class_setup_interface_offsets (eclass);
3228 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
3229 /* we add object for interfaces and the supertypes for the other
3230 * types. The last of the supertypes is the element class itself which we
3231 * already created the explicit interfaces for (so we include it for IEnumerator
3232 * and exclude it for arrays).
3234 if (MONO_CLASS_IS_INTERFACE (eclass))
3237 interface_count += idepth;
3238 if (eclass->rank && eclass->element_class->valuetype) {
3239 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3240 if (valuetype_types [1])
3243 /* IList, ICollection, IEnumerable, IReadOnlyList */
3244 interface_count *= nifaces;
3245 real_count = interface_count;
3246 if (internal_enumerator) {
3247 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3248 if (valuetype_types [1])
3251 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3252 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3253 interfaces [0] = mono_defaults.object_class;
3257 for (i = 0; i < idepth; i++) {
3258 mono_class_init (eclass->supertypes [i]);
3259 interfaces [j] = eclass->supertypes [i];
3263 if (all_interfaces) {
3264 for (i = 0; i < eclass->interface_offsets_count; i++) {
3265 interfaces [j] = eclass->interfaces_packed [i];
3269 for (i = 0; i < eclass->interface_count; i++) {
3270 interfaces [j] = eclass->interfaces [i];
3274 if (valuetype_types [1]) {
3275 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3280 /* instantiate the generic interfaces */
3281 for (i = 0; i < interface_count; i += nifaces) {
3282 MonoClass *iface = interfaces [i];
3284 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3285 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3287 if (eclass->valuetype) {
3288 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3289 if (generic_ireadonlylist_class) {
3290 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3291 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3294 if (!generic_ireadonlylist_class)
3295 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3298 if (internal_enumerator) {
3300 /* instantiate IEnumerator<iface> */
3301 for (i = 0; i < interface_count; i++) {
3302 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3304 j = interface_count;
3305 if (!eclass_is_valuetype) {
3306 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3307 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3310 for (i = 0; i < eclass->idepth; i++) {
3311 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3315 for (i = 0; i < eclass->interface_offsets_count; i++) {
3316 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3320 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3322 if (valuetype_types [1])
3323 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3327 char *type_name = mono_type_get_name_full (&klass->byval_arg, 0);
3328 for (i = 0; i < real_count; ++i) {
3329 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3330 g_print ("%s implements %s\n", type_name, name);
3341 find_array_interface (MonoClass *klass, const char *name)
3344 for (i = 0; i < klass->interface_count; ++i) {
3345 if (strcmp (klass->interfaces [i]->name, name) == 0)
3352 * Return the number of virtual methods.
3353 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3354 * Return -1 on failure.
3355 * FIXME It would be nice if this information could be cached somewhere.
3358 count_virtual_methods (MonoClass *klass)
3360 int i, mcount, vcount = 0;
3362 klass = mono_class_get_generic_type_definition (klass); /*We can find this information by looking at the GTD*/
3364 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
3365 mono_class_setup_methods (klass);
3366 if (mono_class_has_failure (klass))
3369 mcount = mono_class_get_method_count (klass);
3370 for (i = 0; i < mcount; ++i) {
3371 flags = klass->methods [i]->flags;
3372 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3376 int first_idx = mono_class_get_first_method_idx (klass);
3377 mcount = mono_class_get_method_count (klass);
3378 for (i = 0; i < mcount; ++i) {
3379 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
3381 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3389 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3397 m = (l + num_ifaces) / 2;
3398 if (interfaces_full [m] == ic)
3400 if (l == num_ifaces)
3402 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3411 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3413 int i = find_interface (num_ifaces, interfaces_full, ic);
3415 return interface_offsets_full [i];
3420 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3422 int i = find_interface (num_ifaces, interfaces_full, ic);
3426 interface_offsets_full [i] = offset;
3429 for (i = 0; i < num_ifaces; ++i) {
3430 if (interfaces_full [i]) {
3432 if (interfaces_full [i]->interface_id < ic->interface_id)
3435 while (end < num_ifaces && interfaces_full [end]) end++;
3436 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3437 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3439 interfaces_full [i] = ic;
3440 interface_offsets_full [i] = offset;
3446 #ifdef COMPRESSED_INTERFACE_BITMAP
3449 * Compressed interface bitmap design.
3451 * Interface bitmaps take a large amount of memory, because their size is
3452 * linear with the maximum interface id assigned in the process (each interface
3453 * is assigned a unique id as it is loaded). The number of interface classes
3454 * is high because of the many implicit interfaces implemented by arrays (we'll
3455 * need to lazy-load them in the future).
3456 * Most classes implement a very small number of interfaces, so the bitmap is
3457 * sparse. This bitmap needs to be checked by interface casts, so access to the
3458 * needed bit must be fast and doable with few jit instructions.
3460 * The current compression format is as follows:
3461 * *) it is a sequence of one or more two-byte elements
3462 * *) the first byte in the element is the count of empty bitmap bytes
3463 * at the current bitmap position
3464 * *) the second byte in the element is an actual bitmap byte at the current
3467 * As an example, the following compressed bitmap bytes:
3468 * 0x07 0x01 0x00 0x7
3469 * correspond to the following bitmap:
3470 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3472 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3473 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3474 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3478 * mono_compress_bitmap:
3479 * @dest: destination buffer
3480 * @bitmap: bitmap buffer
3481 * @size: size of @bitmap in bytes
3483 * This is a mono internal function.
3484 * The @bitmap data is compressed into a format that is small but
3485 * still searchable in few instructions by the JIT and runtime.
3486 * The compressed data is stored in the buffer pointed to by the
3487 * @dest array. Passing a #NULL value for @dest allows to just compute
3488 * the size of the buffer.
3489 * This compression algorithm assumes the bits set in the bitmap are
3490 * few and far between, like in interface bitmaps.
3491 * Returns: The size of the compressed bitmap in bytes.
3494 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3498 const uint8_t *end = bitmap + size;
3499 while (bitmap < end) {
3500 if (*bitmap || numz == 255) {
3524 * mono_class_interface_match:
3525 * @bitmap: a compressed bitmap buffer
3526 * @id: the index to check in the bitmap
3528 * This is a mono internal function.
3529 * Checks if a bit is set in a compressed interface bitmap. @id must
3530 * be already checked for being smaller than the maximum id encoded in the
3533 * Returns: A non-zero value if bit @id is set in the bitmap @bitmap,
3537 mono_class_interface_match (const uint8_t *bitmap, int id)
3540 id -= bitmap [0] * 8;
3544 return bitmap [1] & (1 << id);
3553 * Return -1 on failure and set klass->has_failure and store a MonoErrorBoxed with the details.
3554 * LOCKING: Acquires the loader lock.
3557 setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite)
3561 int i, j, num_ifaces;
3563 MonoClass **interfaces_full = NULL;
3564 int *interface_offsets_full = NULL;
3566 GPtrArray **ifaces_array = NULL;
3567 int interface_offsets_count;
3568 MonoClass **array_interfaces = NULL;
3569 int num_array_interfaces;
3570 int is_enumerator = FALSE;
3572 mono_loader_lock ();
3574 mono_class_setup_supertypes (klass);
3576 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3577 * implicit interfaces have the property that they are assigned the same slot in the
3578 * vtables for compatible interfaces
3580 array_interfaces = get_implicit_generic_array_interfaces (klass, &num_array_interfaces, &is_enumerator);
3582 /* compute maximum number of slots and maximum interface id */
3584 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3585 ifaces_array = g_new0 (GPtrArray *, klass->idepth);
3586 for (j = 0; j < klass->idepth; j++) {
3587 k = klass->supertypes [j];
3589 num_ifaces += k->interface_count;
3590 for (i = 0; i < k->interface_count; i++) {
3591 ic = k->interfaces [i];
3593 mono_class_init (ic);
3595 if (max_iid < ic->interface_id)
3596 max_iid = ic->interface_id;
3598 ifaces = mono_class_get_implemented_interfaces (k, &error);
3599 if (!mono_error_ok (&error)) {
3600 char *name = mono_type_get_full_name (k);
3601 mono_class_set_type_load_failure (klass, "Error getting the interfaces of %s due to %s", name, mono_error_get_message (&error));
3603 mono_error_cleanup (&error);
3608 num_ifaces += ifaces->len;
3609 for (i = 0; i < ifaces->len; ++i) {
3610 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3611 if (max_iid < ic->interface_id)
3612 max_iid = ic->interface_id;
3614 ifaces_array [j] = ifaces;
3618 for (i = 0; i < num_array_interfaces; ++i) {
3619 ic = array_interfaces [i];
3620 mono_class_init (ic);
3621 if (max_iid < ic->interface_id)
3622 max_iid = ic->interface_id;
3625 if (MONO_CLASS_IS_INTERFACE (klass)) {
3627 if (max_iid < klass->interface_id)
3628 max_iid = klass->interface_id;
3631 /* compute vtable offset for interfaces */
3632 interfaces_full = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3633 interface_offsets_full = (int *)g_malloc (sizeof (int) * num_ifaces);
3635 for (i = 0; i < num_ifaces; i++)
3636 interface_offsets_full [i] = -1;
3638 /* skip the current class */
3639 for (j = 0; j < klass->idepth - 1; j++) {
3640 k = klass->supertypes [j];
3641 ifaces = ifaces_array [j];
3644 for (i = 0; i < ifaces->len; ++i) {
3646 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3648 /*Force the sharing of interface offsets between parent and subtypes.*/
3649 io = mono_class_interface_offset (k, ic);
3651 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3656 g_assert (klass == klass->supertypes [klass->idepth - 1]);
3657 ifaces = ifaces_array [klass->idepth - 1];
3659 for (i = 0; i < ifaces->len; ++i) {
3661 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3662 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3664 count = count_virtual_methods (ic);
3666 char *name = mono_type_get_full_name (ic);
3667 mono_class_set_type_load_failure (klass, "Error calculating interface offset of %s", name);
3676 if (MONO_CLASS_IS_INTERFACE (klass))
3677 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, klass, cur_slot, TRUE);
3679 if (num_array_interfaces) {
3680 if (is_enumerator) {
3681 int ienumerator_idx = find_array_interface (klass, "IEnumerator`1");
3682 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ienumerator_idx]);
3683 g_assert (ienumerator_offset >= 0);
3684 for (i = 0; i < num_array_interfaces; ++i) {
3685 ic = array_interfaces [i];
3686 if (strcmp (ic->name, "IEnumerator`1") == 0)
3687 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3689 g_assert_not_reached ();
3690 /*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);*/
3693 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3694 int ilist_iface_idx = find_array_interface (klass, "IList`1");
3695 MonoClass* ilist_class = klass->interfaces [ilist_iface_idx];
3696 int ireadonlylist_iface_idx = find_array_interface (klass, "IReadOnlyList`1");
3697 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? klass->interfaces [ireadonlylist_iface_idx] : NULL;
3698 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3699 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3700 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3701 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ilist_iface_idx]);
3702 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3703 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3704 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ireadonlylist_iface_idx]) : -1;
3705 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3706 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3707 for (i = 0; i < num_array_interfaces; ++i) {
3709 ic = array_interfaces [i];
3710 if (mono_class_get_generic_class (ic)->container_class == mono_defaults.generic_ilist_class)
3711 offset = ilist_offset;
3712 else if (strcmp (ic->name, "ICollection`1") == 0)
3713 offset = icollection_offset;
3714 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3715 offset = ienumerable_offset;
3716 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3717 offset = ireadonlylist_offset;
3718 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3719 offset = ireadonlycollection_offset;
3721 g_assert_not_reached ();
3722 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3723 /*g_print ("type %s has %s offset at %d (%s)\n", klass->name, ic->name, offset, klass->interfaces [0]->name);*/
3728 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3729 if (interface_offsets_full [i] != -1)
3730 interface_offsets_count ++;
3733 /* Publish the data */
3734 klass->max_interface_id = max_iid;
3736 * We might get called multiple times:
3737 * - mono_class_init ()
3738 * - mono_class_setup_vtable ().
3739 * - mono_class_setup_interface_offsets ().
3740 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3741 * means we have to overwrite those when called from other places (#4440).
3743 if (klass->interfaces_packed) {
3745 g_assert (klass->interface_offsets_count == interface_offsets_count);
3749 klass->interface_offsets_count = interface_offsets_count;
3750 klass->interfaces_packed = (MonoClass **)mono_class_alloc (klass, sizeof (MonoClass*) * interface_offsets_count);
3751 klass->interface_offsets_packed = (guint16 *)mono_class_alloc (klass, sizeof (guint16) * interface_offsets_count);
3752 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3753 #ifdef COMPRESSED_INTERFACE_BITMAP
3754 bitmap = g_malloc0 (bsize);
3756 bitmap = (uint8_t *)mono_class_alloc0 (klass, bsize);
3758 for (i = 0; i < interface_offsets_count; i++) {
3759 guint32 id = interfaces_full [i]->interface_id;
3760 bitmap [id >> 3] |= (1 << (id & 7));
3761 klass->interfaces_packed [i] = interfaces_full [i];
3762 klass->interface_offsets_packed [i] = interface_offsets_full [i];
3763 /*if (num_array_interfaces)
3764 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]);*/
3766 #ifdef COMPRESSED_INTERFACE_BITMAP
3767 i = mono_compress_bitmap (NULL, bitmap, bsize);
3768 klass->interface_bitmap = mono_class_alloc0 (klass, i);
3769 mono_compress_bitmap (klass->interface_bitmap, bitmap, bsize);
3772 klass->interface_bitmap = bitmap;
3776 mono_loader_unlock ();
3778 g_free (interfaces_full);
3779 g_free (interface_offsets_full);
3780 g_free (array_interfaces);
3781 for (i = 0; i < klass->idepth; i++) {
3782 ifaces = ifaces_array [i];
3784 g_ptr_array_free (ifaces, TRUE);
3786 g_free (ifaces_array);
3788 //printf ("JUST DONE: ");
3789 //print_implemented_interfaces (klass);
3795 * Setup interface offsets for interfaces.
3797 * - klass->max_interface_id
3798 * - klass->interface_offsets_count
3799 * - klass->interfaces_packed
3800 * - klass->interface_offsets_packed
3801 * - klass->interface_bitmap
3803 * This function can fail @class.
3806 mono_class_setup_interface_offsets (MonoClass *klass)
3808 setup_interface_offsets (klass, 0, FALSE);
3811 /*Checks if @klass has @parent as one of it's parents type gtd
3815 * Bar<T> : Foo<Bar<Bar<T>>>
3819 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3821 klass = mono_class_get_generic_type_definition (klass);
3822 parent = mono_class_get_generic_type_definition (parent);
3823 mono_class_setup_supertypes (klass);
3824 mono_class_setup_supertypes (parent);
3826 return klass->idepth >= parent->idepth &&
3827 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3831 mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup)
3833 MonoGenericInst *ginst;
3836 if (!mono_class_is_ginst (klass)) {
3837 mono_class_setup_vtable_full (klass, in_setup);
3838 return !mono_class_has_failure (klass);
3841 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup);
3842 if (mono_class_set_type_load_failure_causedby_class (klass, mono_class_get_generic_class (klass)->container_class, "Failed to load generic definition vtable"))
3845 ginst = mono_class_get_generic_class (klass)->context.class_inst;
3846 for (i = 0; i < ginst->type_argc; ++i) {
3848 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3850 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3851 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3852 if (mono_class_has_gtd_parent (klass, arg) || mono_class_has_gtd_parent (arg, klass))
3854 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3855 mono_class_set_type_load_failure (klass, "Failed to load generic parameter %d", i);
3863 * mono_class_setup_vtable:
3865 * Creates the generic vtable of CLASS.
3866 * Initializes the following fields in MonoClass:
3869 * Plus all the fields initialized by setup_interface_offsets ().
3870 * If there is an error during vtable construction, klass->has_failure
3871 * is set and details are stored in a MonoErrorBoxed.
3873 * LOCKING: Acquires the loader lock.
3876 mono_class_setup_vtable (MonoClass *klass)
3878 mono_class_setup_vtable_full (klass, NULL);
3882 mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
3885 MonoMethod **overrides;
3886 MonoGenericContext *context;
3894 if (MONO_CLASS_IS_INTERFACE (klass)) {
3895 /* This sets method->slot for all methods if this is an interface */
3896 mono_class_setup_methods (klass);
3900 if (mono_class_has_failure (klass))
3903 if (g_list_find (in_setup, klass))
3906 mono_loader_lock ();
3908 if (klass->vtable) {
3909 mono_loader_unlock ();
3913 mono_stats.generic_vtable_count ++;
3914 in_setup = g_list_prepend (in_setup, klass);
3916 if (mono_class_is_ginst (klass)) {
3917 if (!mono_class_check_vtable_constraints (klass, in_setup)) {
3918 mono_loader_unlock ();
3919 g_list_remove (in_setup, klass);
3923 context = mono_class_get_context (klass);
3924 type_token = mono_class_get_generic_class (klass)->container_class->type_token;
3926 context = (MonoGenericContext *) mono_class_try_get_generic_container (klass); //FIXME is this a case of a try?
3927 type_token = klass->type_token;
3930 if (image_is_dynamic (klass->image)) {
3931 /* Generic instances can have zero method overrides without causing any harm.
3932 * This is true since we don't do layout all over again for them, we simply inflate
3933 * the layout of the parent.
3935 mono_reflection_get_dynamic_overrides (klass, &overrides, &onum, &error);
3936 if (!is_ok (&error)) {
3937 mono_loader_unlock ();
3938 g_list_remove (in_setup, klass);
3939 mono_class_set_type_load_failure (klass, "Could not load list of method overrides due to %s", mono_error_get_message (&error));
3940 mono_error_cleanup (&error);
3944 /* The following call fails if there are missing methods in the type */
3945 /* FIXME it's probably a good idea to avoid this for generic instances. */
3946 ok = mono_class_get_overrides_full (klass->image, type_token, &overrides, &onum, context);
3950 mono_class_setup_vtable_general (klass, overrides, onum, in_setup);
3952 mono_class_set_type_load_failure (klass, "Could not load list of method overrides");
3956 mono_loader_unlock ();
3957 g_list_remove (in_setup, klass);
3962 #define DEBUG_INTERFACE_VTABLE_CODE 0
3963 #define TRACE_INTERFACE_VTABLE_CODE 0
3964 #define VERIFY_INTERFACE_VTABLE_CODE 0
3965 #define VTABLE_SELECTOR (1)
3967 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3968 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3969 if (!(VTABLE_SELECTOR)) break; \
3973 #define DEBUG_INTERFACE_VTABLE(stmt)
3976 #if TRACE_INTERFACE_VTABLE_CODE
3977 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3978 if (!(VTABLE_SELECTOR)) break; \
3982 #define TRACE_INTERFACE_VTABLE(stmt)
3985 #if VERIFY_INTERFACE_VTABLE_CODE
3986 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3987 if (!(VTABLE_SELECTOR)) break; \
3991 #define VERIFY_INTERFACE_VTABLE(stmt)
3995 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3997 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
4001 GString *res = g_string_new ("");
4003 g_string_append_c (res, '(');
4004 for (i = 0; i < sig->param_count; ++i) {
4006 g_string_append_c (res, ',');
4007 mono_type_get_desc (res, sig->params [i], include_namespace);
4009 g_string_append (res, ")=>");
4010 if (sig->ret != NULL) {
4011 mono_type_get_desc (res, sig->ret, include_namespace);
4013 g_string_append (res, "NULL");
4016 g_string_free (res, FALSE);
4020 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
4021 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
4022 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
4023 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
4031 is_wcf_hack_disabled (void)
4033 static gboolean disabled;
4034 static gboolean inited = FALSE;
4036 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
4043 check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
4045 MonoMethodSignature *cmsig, *imsig;
4046 if (strcmp (im->name, cm->name) == 0) {
4047 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
4048 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
4051 if (! slot_is_empty) {
4052 if (require_newslot) {
4053 if (! interface_is_explicitly_implemented_by_class) {
4054 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
4057 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4058 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
4062 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
4065 cmsig = mono_method_signature (cm);
4066 imsig = mono_method_signature (im);
4067 if (!cmsig || !imsig) {
4068 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
4072 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4073 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
4074 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4075 TRACE_INTERFACE_VTABLE (printf ("]"));
4078 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
4079 if (mono_security_core_clr_enabled ())
4080 mono_security_core_clr_check_override (klass, cm, im);
4082 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
4083 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4084 char *body_name = mono_method_full_name (cm, TRUE);
4085 char *decl_name = mono_method_full_name (im, TRUE);
4086 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4094 MonoClass *ic = im->klass;
4095 const char *ic_name_space = ic->name_space;
4096 const char *ic_name = ic->name;
4099 if (! require_newslot) {
4100 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
4103 if (cm->klass->rank == 0) {
4104 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
4107 cmsig = mono_method_signature (cm);
4108 imsig = mono_method_signature (im);
4109 if (!cmsig || !imsig) {
4110 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
4114 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4115 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
4116 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4117 TRACE_INTERFACE_VTABLE (printf ("]"));
4120 if (mono_class_get_image (ic) != mono_defaults.corlib) {
4121 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
4124 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
4125 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
4128 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))) {
4129 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
4133 subname = strstr (cm->name, ic_name_space);
4134 if (subname != cm->name) {
4135 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
4138 subname += strlen (ic_name_space);
4139 if (subname [0] != '.') {
4140 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
4144 if (strstr (subname, ic_name) != subname) {
4145 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
4148 subname += strlen (ic_name);
4149 if (subname [0] != '.') {
4150 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
4154 if (strcmp (subname, im->name) != 0) {
4155 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
4159 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
4160 if (mono_security_core_clr_enabled ())
4161 mono_security_core_clr_check_override (klass, cm, im);
4163 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
4164 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4165 char *body_name = mono_method_full_name (cm, TRUE);
4166 char *decl_name = mono_method_full_name (im, TRUE);
4167 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4177 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
4179 foreach_override (gpointer key, gpointer value, gpointer user_data) {
4180 MonoMethod *method = key;
4181 MonoMethod *override = value;
4182 MonoClass *method_class = mono_method_get_class (method);
4183 MonoClass *override_class = mono_method_get_class (override);
4185 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
4186 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
4187 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
4190 print_overrides (GHashTable *override_map, const char *message) {
4192 printf ("Override map \"%s\" START:\n", message);
4193 g_hash_table_foreach (override_map, foreach_override, NULL);
4194 printf ("Override map \"%s\" END.\n", message);
4196 printf ("Override map \"%s\" EMPTY.\n", message);
4200 print_vtable_full (MonoClass *klass, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
4201 char *full_name = mono_type_full_name (&klass->byval_arg);
4205 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
4207 if (print_interfaces) {
4208 print_implemented_interfaces (klass);
4209 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
4212 if (klass->parent) {
4213 parent_size = klass->parent->vtable_size;
4217 for (i = 0; i < size; ++i) {
4218 MonoMethod *cm = vtable [i];
4219 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
4220 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
4222 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
4230 #if VERIFY_INTERFACE_VTABLE_CODE
4232 mono_method_try_get_vtable_index (MonoMethod *method)
4234 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4235 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4236 if (imethod->declaring->is_generic)
4237 return imethod->declaring->slot;
4239 return method->slot;
4243 mono_class_verify_vtable (MonoClass *klass)
4246 char *full_name = mono_type_full_name (&klass->byval_arg);
4248 printf ("*** Verifying VTable of class '%s' \n", full_name);
4252 if (!klass->methods)
4255 count = mono_class_method_count (klass);
4256 for (i = 0; i < count; ++i) {
4257 MonoMethod *cm = klass->methods [i];
4260 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4264 full_name = mono_method_full_name (cm, TRUE);
4266 slot = mono_method_try_get_vtable_index (cm);
4268 if (slot >= klass->vtable_size) {
4269 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, klass->vtable_size);
4273 if (slot >= 0 && klass->vtable [slot] != cm && (klass->vtable [slot])) {
4274 char *other_name = klass->vtable [slot] ? mono_method_full_name (klass->vtable [slot], TRUE) : g_strdup ("[null value]");
4275 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4276 g_free (other_name);
4279 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4286 print_unimplemented_interface_method_info (MonoClass *klass, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum)
4289 char *method_signature;
4292 for (index = 0; index < onum; ++index) {
4293 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4294 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4296 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4297 type_name = mono_type_full_name (&klass->byval_arg);
4298 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4299 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4300 g_free (method_signature);
4302 mono_class_setup_methods (klass);
4303 if (mono_class_has_failure (klass)) {
4304 char *name = mono_type_get_full_name (klass);
4305 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4309 mcount = mono_class_get_method_count (klass);
4310 for (index = 0; index < mcount; ++index) {
4311 MonoMethod *cm = klass->methods [index];
4312 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4314 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4315 g_free (method_signature);
4320 mono_method_get_method_definition (MonoMethod *method)
4322 while (method->is_inflated)
4323 method = ((MonoMethodInflated*)method)->declaring;
4328 verify_class_overrides (MonoClass *klass, MonoMethod **overrides, int onum)
4332 for (i = 0; i < onum; ++i) {
4333 MonoMethod *decl = overrides [i * 2];
4334 MonoMethod *body = overrides [i * 2 + 1];
4336 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (klass)) {
4337 mono_class_set_type_load_failure (klass, "Method belongs to a different class than the declared one");
4341 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4342 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4343 mono_class_set_type_load_failure (klass, "Method must not be static to override a base type");
4345 mono_class_set_type_load_failure (klass, "Method must be virtual to override a base type");
4349 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4350 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4351 mono_class_set_type_load_failure (klass, "Cannot override a static method in a base type");
4353 mono_class_set_type_load_failure (klass, "Cannot override a non virtual method in a base type");
4357 if (!mono_class_is_assignable_from_slow (decl->klass, klass)) {
4358 mono_class_set_type_load_failure (klass, "Method overrides a class or interface that is not extended or implemented by this type");
4362 body = mono_method_get_method_definition (body);
4363 decl = mono_method_get_method_definition (decl);
4365 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4366 char *body_name = mono_method_full_name (body, TRUE);
4367 char *decl_name = mono_method_full_name (decl, TRUE);
4368 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4378 mono_class_need_stelemref_method (MonoClass *klass)
4380 return klass->rank == 1 && MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg);
4384 * LOCKING: this is supposed to be called with the loader lock held.
4387 mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int onum, GList *in_setup)
4391 MonoMethod **vtable;
4392 int i, max_vtsize = 0, cur_slot = 0;
4394 GPtrArray *ifaces = NULL;
4395 GHashTable *override_map = NULL;
4397 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4398 int first_non_interface_slot;
4400 GSList *virt_methods = NULL, *l;
4401 int stelemref_slot = 0;
4406 if (overrides && !verify_class_overrides (klass, overrides, onum))
4409 ifaces = mono_class_get_implemented_interfaces (klass, &error);
4410 if (!mono_error_ok (&error)) {
4411 char *name = mono_type_get_full_name (klass);
4412 mono_class_set_type_load_failure (klass, "Could not resolve %s interfaces due to %s", name, mono_error_get_message (&error));
4414 mono_error_cleanup (&error);
4416 } else if (ifaces) {
4417 for (i = 0; i < ifaces->len; i++) {
4418 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
4419 max_vtsize += mono_class_get_method_count (ic);
4421 g_ptr_array_free (ifaces, TRUE);
4425 if (klass->parent) {
4426 mono_class_init (klass->parent);
4427 mono_class_setup_vtable_full (klass->parent, in_setup);
4429 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class failed to load"))
4432 max_vtsize += klass->parent->vtable_size;
4433 cur_slot = klass->parent->vtable_size;
4436 max_vtsize += mono_class_get_method_count (klass);
4438 /*Array have a slot for stelemref*/
4439 if (mono_class_need_stelemref_method (klass)) {
4440 stelemref_slot = cur_slot;
4445 vtable = (MonoMethod **)alloca (sizeof (gpointer) * max_vtsize);
4446 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4448 /* printf ("METAINIT %s.%s\n", klass->name_space, klass->name); */
4450 cur_slot = setup_interface_offsets (klass, cur_slot, TRUE);
4451 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4454 max_iid = klass->max_interface_id;
4455 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4457 /* Optimized version for generic instances */
4458 if (mono_class_is_ginst (klass)) {
4460 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4463 mono_class_setup_vtable_full (gklass, in_setup);
4464 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Could not load generic definition"))
4467 tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * gklass->vtable_size);
4468 klass->vtable_size = gklass->vtable_size;
4469 for (i = 0; i < gklass->vtable_size; ++i)
4470 if (gklass->vtable [i]) {
4471 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], klass, mono_class_get_context (klass), &error);
4472 if (!mono_error_ok (&error)) {
4473 mono_class_set_type_load_failure (klass, "Could not inflate method due to %s", mono_error_get_message (&error));
4474 mono_error_cleanup (&error);
4478 tmp [i]->slot = gklass->vtable [i]->slot;
4480 mono_memory_barrier ();
4481 klass->vtable = tmp;
4483 /* Have to set method->slot for abstract virtual methods */
4484 if (klass->methods && gklass->methods) {
4485 int mcount = mono_class_get_method_count (klass);
4486 for (i = 0; i < mcount; ++i)
4487 if (klass->methods [i]->slot == -1)
4488 klass->methods [i]->slot = gklass->methods [i]->slot;
4494 if (klass->parent && klass->parent->vtable_size) {
4495 MonoClass *parent = klass->parent;
4498 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4500 // Also inherit parent interface vtables, just as a starting point.
4501 // This is needed otherwise bug-77127.exe fails when the property methods
4502 // have different names in the iterface and the class, because for child
4503 // classes the ".override" information is not used anymore.
4504 for (i = 0; i < parent->interface_offsets_count; i++) {
4505 MonoClass *parent_interface = parent->interfaces_packed [i];
4506 int interface_offset = mono_class_interface_offset (klass, parent_interface);
4507 /*FIXME this is now dead code as this condition will never hold true.
4508 Since interface offsets are inherited then the offset of an interface implemented
4509 by a parent will never be the out of it's vtable boundary.
4511 if (interface_offset >= parent->vtable_size) {
4512 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4515 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4516 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4517 int mcount = mono_class_get_method_count (parent_interface);
4518 for (j = 0; j < mcount && !mono_class_has_failure (klass); j++) {
4519 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4520 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4521 parent_interface_offset + j, parent_interface_offset, j,
4522 interface_offset + j, interface_offset, j));
4529 /*Array have a slot for stelemref*/
4530 if (mono_class_need_stelemref_method (klass)) {
4531 MonoMethod *method = mono_marshal_get_virtual_stelemref (klass);
4533 method->slot = stelemref_slot;
4535 g_assert (method->slot == stelemref_slot);
4537 vtable [stelemref_slot] = method;
4540 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4541 /* override interface methods */
4542 for (i = 0; i < onum; i++) {
4543 MonoMethod *decl = overrides [i*2];
4544 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4546 dslot = mono_method_get_vtable_slot (decl);
4548 mono_class_set_type_load_failure (klass, "");
4552 dslot += mono_class_interface_offset (klass, decl->klass);
4553 vtable [dslot] = overrides [i*2 + 1];
4554 vtable [dslot]->slot = dslot;
4556 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4558 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4560 if (mono_security_core_clr_enabled ())
4561 mono_security_core_clr_check_override (klass, vtable [dslot], decl);
4564 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4565 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4568 * Create a list of virtual methods to avoid calling
4569 * mono_class_get_virtual_methods () which is slow because of the metadata
4573 gpointer iter = NULL;
4576 virt_methods = NULL;
4577 while ((cm = mono_class_get_virtual_methods (klass, &iter))) {
4578 virt_methods = g_slist_prepend (virt_methods, cm);
4580 if (mono_class_has_failure (klass))
4584 // Loop on all implemented interfaces...
4585 for (i = 0; i < klass->interface_offsets_count; i++) {
4586 MonoClass *parent = klass->parent;
4588 gboolean interface_is_explicitly_implemented_by_class;
4591 ic = klass->interfaces_packed [i];
4592 ic_offset = mono_class_interface_offset (klass, ic);
4594 mono_class_setup_methods (ic);
4595 if (mono_class_has_failure (ic))
4598 // Check if this interface is explicitly implemented (instead of just inherited)
4599 if (parent != NULL) {
4600 int implemented_interfaces_index;
4601 interface_is_explicitly_implemented_by_class = FALSE;
4602 for (implemented_interfaces_index = 0; implemented_interfaces_index < klass->interface_count; implemented_interfaces_index++) {
4603 if (ic == klass->interfaces [implemented_interfaces_index]) {
4604 interface_is_explicitly_implemented_by_class = TRUE;
4609 interface_is_explicitly_implemented_by_class = TRUE;
4612 // Loop on all interface methods...
4613 int mcount = mono_class_get_method_count (ic);
4614 for (im_index = 0; im_index < mcount; im_index++) {
4615 MonoMethod *im = ic->methods [im_index];
4616 int im_slot = ic_offset + im->slot;
4617 MonoMethod *override_im = (override_map != NULL) ? (MonoMethod *)g_hash_table_lookup (override_map, im) : NULL;
4619 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4622 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4624 // If there is an explicit implementation, just use it right away,
4625 // otherwise look for a matching method
4626 if (override_im == NULL) {
4630 // First look for a suitable method among the class methods
4631 for (l = virt_methods; l; l = l->next) {
4632 cm = (MonoMethod *)l->data;
4633 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)));
4634 if (check_interface_method_override (klass, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
4635 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4636 vtable [im_slot] = cm;
4637 /* Why do we need this? */
4642 TRACE_INTERFACE_VTABLE (printf ("\n"));
4643 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4647 // If the slot is still empty, look in all the inherited virtual methods...
4648 if ((vtable [im_slot] == NULL) && klass->parent != NULL) {
4649 MonoClass *parent = klass->parent;
4650 // Reverse order, so that last added methods are preferred
4651 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4652 MonoMethod *cm = parent->vtable [cm_index];
4654 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));
4655 if ((cm != NULL) && check_interface_method_override (klass, im, cm, FALSE, FALSE, TRUE)) {
4656 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4657 vtable [im_slot] = cm;
4658 /* Why do we need this? */
4664 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4666 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4670 g_assert (vtable [im_slot] == override_im);
4675 // If the class is not abstract, check that all its interface slots are full.
4676 // The check is done here and not directly at the end of the loop above because
4677 // it can happen (for injected generic array interfaces) that the same slot is
4678 // processed multiple times (those interfaces have overlapping slots), and it
4679 // will not always be the first pass the one that fills the slot.
4680 if (!mono_class_is_abstract (klass)) {
4681 for (i = 0; i < klass->interface_offsets_count; i++) {
4685 ic = klass->interfaces_packed [i];
4686 ic_offset = mono_class_interface_offset (klass, ic);
4688 int mcount = mono_class_get_method_count (ic);
4689 for (im_index = 0; im_index < mcount; im_index++) {
4690 MonoMethod *im = ic->methods [im_index];
4691 int im_slot = ic_offset + im->slot;
4693 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4696 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4697 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4698 if (vtable [im_slot] == NULL) {
4699 print_unimplemented_interface_method_info (klass, ic, im, im_slot, overrides, onum);
4706 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4707 for (l = virt_methods; l; l = l->next) {
4708 cm = (MonoMethod *)l->data;
4710 * If the method is REUSE_SLOT, we must check in the
4711 * base class for a method to override.
4713 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4715 for (k = klass->parent; k ; k = k->parent) {
4720 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4721 MonoMethodSignature *cmsig, *m1sig;
4723 cmsig = mono_method_signature (cm);
4724 m1sig = mono_method_signature (m1);
4726 if (!cmsig || !m1sig) {
4727 /* FIXME proper error message */
4728 mono_class_set_type_load_failure (klass, "");
4732 if (!strcmp(cm->name, m1->name) &&
4733 mono_metadata_signature_equal (cmsig, m1sig)) {
4735 if (mono_security_core_clr_enabled ())
4736 mono_security_core_clr_check_override (klass, cm, m1);
4738 slot = mono_method_get_vtable_slot (m1);
4742 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4743 char *body_name = mono_method_full_name (cm, TRUE);
4744 char *decl_name = mono_method_full_name (m1, TRUE);
4745 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4751 g_assert (cm->slot < max_vtsize);
4753 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4754 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4755 mono_method_full_name (m1, 1), m1,
4756 mono_method_full_name (cm, 1), cm));
4757 g_hash_table_insert (override_map, m1, cm);
4761 if (mono_class_has_failure (k))
4771 /*Non final newslot methods must be given a non-interface vtable slot*/
4772 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4776 cm->slot = cur_slot++;
4778 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4779 vtable [cm->slot] = cm;
4782 /* override non interface methods */
4783 for (i = 0; i < onum; i++) {
4784 MonoMethod *decl = overrides [i*2];
4785 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4786 g_assert (decl->slot != -1);
4787 vtable [decl->slot] = overrides [i*2 + 1];
4788 overrides [i * 2 + 1]->slot = decl->slot;
4790 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4791 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4792 mono_method_full_name (decl, 1), decl,
4793 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4794 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4796 if (mono_security_core_clr_enabled ())
4797 mono_security_core_clr_check_override (klass, vtable [decl->slot], decl);
4802 * If a method occupies more than one place in the vtable, and it is
4803 * overriden, then change the other occurances too.
4808 for (i = 0; i < max_vtsize; ++i)
4810 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4812 cm = (MonoMethod *)g_hash_table_lookup (override_map, vtable [i]);
4817 g_hash_table_destroy (override_map);
4818 override_map = NULL;
4821 g_slist_free (virt_methods);
4822 virt_methods = NULL;
4824 /* Ensure that all vtable slots are filled with concrete instance methods */
4825 if (!mono_class_is_abstract (klass)) {
4826 for (i = 0; i < cur_slot; ++i) {
4827 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4828 char *type_name = mono_type_get_full_name (klass);
4829 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4830 mono_class_set_type_load_failure (klass, "Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name);
4832 g_free (method_name);
4838 if (mono_class_is_ginst (klass)) {
4839 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4841 mono_class_init (gklass);
4843 klass->vtable_size = MAX (gklass->vtable_size, cur_slot);
4845 /* Check that the vtable_size value computed in mono_class_init () is correct */
4846 if (klass->vtable_size)
4847 g_assert (cur_slot == klass->vtable_size);
4848 klass->vtable_size = cur_slot;
4851 /* Try to share the vtable with our parent. */
4852 if (klass->parent && (klass->parent->vtable_size == klass->vtable_size) && (memcmp (klass->parent->vtable, vtable, sizeof (gpointer) * klass->vtable_size) == 0)) {
4853 mono_memory_barrier ();
4854 klass->vtable = klass->parent->vtable;
4856 MonoMethod **tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * klass->vtable_size);
4857 memcpy (tmp, vtable, sizeof (gpointer) * klass->vtable_size);
4858 mono_memory_barrier ();
4859 klass->vtable = tmp;
4862 DEBUG_INTERFACE_VTABLE (print_vtable_full (klass, klass->vtable, klass->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4863 if (mono_print_vtable) {
4866 print_implemented_interfaces (klass);
4868 for (i = 0; i <= max_iid; i++)
4869 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
4872 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&klass->byval_arg),
4873 klass->vtable_size, icount);
4875 for (i = 0; i < cur_slot; ++i) {
4880 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4881 mono_method_full_name (cm, TRUE));
4887 printf ("Interfaces %s.%s (max_iid = %d)\n", klass->name_space,
4888 klass->name, max_iid);
4890 for (i = 0; i < klass->interface_count; i++) {
4891 ic = klass->interfaces [i];
4892 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4893 mono_class_interface_offset (klass, ic),
4894 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4897 for (k = klass->parent; k ; k = k->parent) {
4898 for (i = 0; i < k->interface_count; i++) {
4899 ic = k->interfaces [i];
4900 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4901 mono_class_interface_offset (klass, ic),
4902 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4908 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (klass));
4913 char *name = mono_type_get_full_name (klass);
4914 mono_class_set_type_load_failure (klass, "VTable setup of type %s failed", name);
4917 g_hash_table_destroy (override_map);
4919 g_slist_free (virt_methods);
4924 * mono_method_get_vtable_slot:
4926 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4927 * LOCKING: Acquires the loader lock.
4929 * FIXME Use proper MonoError machinery here.
4932 mono_method_get_vtable_slot (MonoMethod *method)
4934 if (method->slot == -1) {
4935 mono_class_setup_vtable (method->klass);
4936 if (mono_class_has_failure (method->klass))
4938 if (method->slot == -1) {
4942 if (!mono_class_is_ginst (method->klass)) {
4943 g_assert (method->is_inflated);
4944 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4947 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4948 g_assert (mono_class_is_ginst (method->klass));
4949 gklass = mono_class_get_generic_class (method->klass)->container_class;
4950 mono_class_setup_methods (method->klass);
4951 g_assert (method->klass->methods);
4952 mcount = mono_class_get_method_count (method->klass);
4953 for (i = 0; i < mcount; ++i) {
4954 if (method->klass->methods [i] == method)
4957 g_assert (i < mcount);
4958 g_assert (gklass->methods);
4959 method->slot = gklass->methods [i]->slot;
4961 g_assert (method->slot != -1);
4963 return method->slot;
4967 * mono_method_get_vtable_index:
4970 * Returns the index into the runtime vtable to access the method or,
4971 * in the case of a virtual generic method, the virtual generic method
4972 * thunk. Returns -1 on failure.
4974 * FIXME Use proper MonoError machinery here.
4977 mono_method_get_vtable_index (MonoMethod *method)
4979 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4980 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4981 if (imethod->declaring->is_generic)
4982 return mono_method_get_vtable_slot (imethod->declaring);
4984 return mono_method_get_vtable_slot (method);
4987 static MonoMethod *default_ghc = NULL;
4988 static MonoMethod *default_finalize = NULL;
4989 static int finalize_slot = -1;
4990 static int ghc_slot = -1;
4993 initialize_object_slots (MonoClass *klass)
4998 if (klass == mono_defaults.object_class) {
4999 mono_class_setup_vtable (klass);
5000 for (i = 0; i < klass->vtable_size; ++i) {
5001 MonoMethod *cm = klass->vtable [i];
5003 if (!strcmp (cm->name, "GetHashCode"))
5005 else if (!strcmp (cm->name, "Finalize"))
5009 g_assert (ghc_slot > 0);
5010 default_ghc = klass->vtable [ghc_slot];
5012 g_assert (finalize_slot > 0);
5013 default_finalize = klass->vtable [finalize_slot];
5018 MonoMethod *array_method;
5020 } GenericArrayMethodInfo;
5022 static int generic_array_method_num = 0;
5023 static GenericArrayMethodInfo *generic_array_method_info = NULL;
5026 generic_array_methods (MonoClass *klass)
5028 int i, count_generic = 0, mcount;
5029 GList *list = NULL, *tmp;
5030 if (generic_array_method_num)
5031 return generic_array_method_num;
5032 mono_class_setup_methods (klass->parent); /*This is setting up System.Array*/
5033 g_assert (!mono_class_has_failure (klass->parent)); /*So hitting this assert is a huge problem*/
5034 mcount = mono_class_get_method_count (klass->parent);
5035 for (i = 0; i < mcount; i++) {
5036 MonoMethod *m = klass->parent->methods [i];
5037 if (!strncmp (m->name, "InternalArray__", 15)) {
5039 list = g_list_prepend (list, m);
5042 list = g_list_reverse (list);
5043 generic_array_method_info = (GenericArrayMethodInfo *)mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
5045 for (tmp = list; tmp; tmp = tmp->next) {
5046 const char *mname, *iname;
5048 MonoMethod *m = (MonoMethod *)tmp->data;
5049 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
5050 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
5052 generic_array_method_info [i].array_method = m;
5053 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
5054 iname = "System.Collections.Generic.ICollection`1.";
5055 mname = m->name + 27;
5056 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
5057 iname = "System.Collections.Generic.IEnumerable`1.";
5058 mname = m->name + 27;
5059 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
5060 iname = "System.Collections.Generic.IReadOnlyList`1.";
5061 mname = m->name + strlen (ireadonlylist_prefix);
5062 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
5063 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
5064 mname = m->name + strlen (ireadonlycollection_prefix);
5065 } else if (!strncmp (m->name, "InternalArray__", 15)) {
5066 iname = "System.Collections.Generic.IList`1.";
5067 mname = m->name + 15;
5069 g_assert_not_reached ();
5072 name = (gchar *)mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
5073 strcpy (name, iname);
5074 strcpy (name + strlen (iname), mname);
5075 generic_array_method_info [i].name = name;
5078 /*g_print ("array generic methods: %d\n", count_generic);*/
5080 generic_array_method_num = count_generic;
5082 return generic_array_method_num;
5086 setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos)
5088 MonoGenericContext tmp_context;
5091 tmp_context.class_inst = NULL;
5092 tmp_context.method_inst = mono_class_get_generic_class (iface)->context.class_inst;
5093 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
5095 for (i = 0; i < generic_array_method_num; i++) {
5097 MonoMethod *m = generic_array_method_info [i].array_method;
5098 MonoMethod *inflated;
5100 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
5101 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
5102 methods [pos++] = mono_marshal_get_generic_array_helper (klass, iface, generic_array_method_info [i].name, inflated);
5107 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
5109 int null_length = strlen ("(null)");
5110 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
5111 char *s = (char *)mono_image_alloc (image, len);
5114 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
5115 g_assert (result == len - 1);
5122 * @klass: the class to initialize
5124 * Compute the instance_size, class_size and other infos that cannot be
5125 * computed at mono_class_get() time. Also compute vtable_size if possible.
5126 * Returns TRUE on success or FALSE if there was a problem in loading
5127 * the type (incorrect assemblies, missing assemblies, methods, etc).
5128 * Initializes the following fields in @klass:
5129 * - all the fields initialized by mono_class_init_sizes ()
5134 * LOCKING: Acquires the loader lock.
5137 mono_class_init (MonoClass *klass)
5139 int i, vtable_size = 0, array_method_count = 0;
5140 MonoCachedClassInfo cached_info;
5141 gboolean has_cached_info;
5142 gboolean locked = FALSE;
5143 gboolean ghcimpl = FALSE;
5144 gboolean has_cctor = FALSE;
5145 int first_iface_slot = 0;
5149 /* Double-checking locking pattern */
5150 if (klass->inited || mono_class_has_failure (klass))
5151 return !mono_class_has_failure (klass);
5153 /*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/
5156 * This function can recursively call itself.
5158 GSList *init_list = (GSList *)mono_native_tls_get_value (init_pending_tls_id);
5159 if (g_slist_find (init_list, klass)) {
5160 mono_class_set_type_load_failure (klass, "Recursive type definition detected");
5163 init_list = g_slist_prepend (init_list, klass);
5164 mono_native_tls_set_value (init_pending_tls_id, init_list);
5167 * We want to avoid doing complicated work inside locks, so we compute all the required
5168 * information and write it to @klass inside a lock.
5171 if (mono_verifier_is_enabled_for_class (klass) && !mono_verifier_verify_class (klass)) {
5172 mono_class_set_type_load_failure (klass, "%s", concat_two_strings_with_zero (klass->image, klass->name, klass->image->assembly_name));
5176 if (klass->byval_arg.type == MONO_TYPE_ARRAY || klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5177 MonoClass *element_class = klass->element_class;
5178 if (!element_class->inited)
5179 mono_class_init (element_class);
5180 if (mono_class_set_type_load_failure_causedby_class (klass, element_class, "Could not load array element class"))
5184 mono_stats.initialized_class_count++;
5186 if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic) {
5187 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5189 mono_class_init (gklass);
5190 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic Type Definition failed to init"))
5193 mono_class_setup_interface_id (klass);
5196 if (klass->parent && !klass->parent->inited)
5197 mono_class_init (klass->parent);
5199 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
5201 /* Compute instance size etc. */
5202 init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
5203 if (mono_class_has_failure (klass))
5206 mono_class_setup_supertypes (klass);
5209 initialize_object_slots (klass);
5212 * Initialize the rest of the data without creating a generic vtable if possible.
5213 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5214 * also avoid computing a generic vtable.
5216 if (has_cached_info) {
5218 vtable_size = cached_info.vtable_size;
5219 ghcimpl = cached_info.ghcimpl;
5220 has_cctor = cached_info.has_cctor;
5221 } else if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5222 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5223 * The first slot if for array with.
5225 static int szarray_vtable_size[2] = { 0 };
5227 int slot = MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg) ? 0 : 1;
5230 if (!szarray_vtable_size [slot]) {
5231 mono_class_setup_vtable (klass);
5232 szarray_vtable_size [slot] = klass->vtable_size;
5233 vtable_size = klass->vtable_size;
5235 vtable_size = szarray_vtable_size[slot];
5237 } else if (mono_class_is_ginst (klass) && !MONO_CLASS_IS_INTERFACE (klass)) {
5238 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5240 /* Generic instance case */
5241 ghcimpl = gklass->ghcimpl;
5242 has_cctor = gklass->has_cctor;
5244 mono_class_setup_vtable (gklass);
5245 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to init"))
5248 vtable_size = gklass->vtable_size;
5252 /* ghcimpl is not currently used
5254 if (klass->parent) {
5255 MonoMethod *cmethod = klass->vtable [ghc_slot];
5256 if (cmethod->is_inflated)
5257 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5258 if (cmethod == default_ghc) {
5264 /* C# doesn't allow interfaces to have cctors */
5265 if (!MONO_CLASS_IS_INTERFACE (klass) || klass->image != mono_defaults.corlib) {
5266 MonoMethod *cmethod = NULL;
5268 if (mono_class_is_ginst (klass)) {
5269 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5271 /* Generic instance case */
5272 ghcimpl = gklass->ghcimpl;
5273 has_cctor = gklass->has_cctor;
5274 } else if (klass->type_token && !image_is_dynamic(klass->image)) {
5275 cmethod = find_method_in_metadata (klass, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5276 /* The find_method function ignores the 'flags' argument */
5277 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5280 mono_class_setup_methods (klass);
5281 if (mono_class_has_failure (klass))
5284 int mcount = mono_class_get_method_count (klass);
5285 for (i = 0; i < mcount; ++i) {
5286 MonoMethod *method = klass->methods [i];
5287 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5288 (strcmp (".cctor", method->name) == 0)) {
5298 array_method_count = 3 + (klass->rank > 1? 2: 1);
5300 if (klass->interface_count) {
5301 int count_generic = generic_array_methods (klass);
5302 array_method_count += klass->interface_count * count_generic;
5306 if (klass->parent) {
5307 if (!klass->parent->vtable_size)
5308 mono_class_setup_vtable (klass->parent);
5309 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class vtable failed to initialize"))
5311 g_assert (klass->parent->vtable_size);
5312 first_iface_slot = klass->parent->vtable_size;
5313 if (mono_class_need_stelemref_method (klass))
5318 * Do the actual changes to @klass inside the loader lock
5320 mono_loader_lock ();
5323 if (klass->inited || mono_class_has_failure (klass)) {
5324 mono_loader_unlock ();
5325 /* Somebody might have gotten in before us */
5326 return !mono_class_has_failure (klass);
5329 mono_stats.initialized_class_count++;
5331 if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic)
5332 mono_stats.generic_class_count++;
5334 if (mono_class_is_ginst (klass) || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
5335 klass->nested_classes_inited = TRUE;
5336 klass->ghcimpl = ghcimpl;
5337 klass->has_cctor = has_cctor;
5339 klass->vtable_size = vtable_size;
5340 if (has_cached_info) {
5341 klass->has_finalize = cached_info.has_finalize;
5342 klass->has_finalize_inited = TRUE;
5345 mono_class_set_method_count (klass, array_method_count);
5347 mono_loader_unlock ();
5350 setup_interface_offsets (klass, first_iface_slot, TRUE);
5352 if (mono_security_core_clr_enabled ())
5353 mono_security_core_clr_check_inheritance (klass);
5355 if (mono_class_is_ginst (klass) && !mono_verifier_class_is_valid_generic_instantiation (klass))
5356 mono_class_set_type_load_failure (klass, "Invalid generic instantiation");
5361 init_list = g_slist_remove (init_list, klass);
5362 mono_native_tls_set_value (init_pending_tls_id, init_list);
5364 /* Because of the double-checking locking pattern */
5365 mono_memory_barrier ();
5369 mono_loader_unlock ();
5371 return !mono_class_has_failure (klass);
5375 * mono_class_has_finalizer:
5377 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5381 mono_class_has_finalizer (MonoClass *klass)
5383 gboolean has_finalize = FALSE;
5385 if (klass->has_finalize_inited)
5386 return klass->has_finalize;
5388 /* Interfaces and valuetypes are not supposed to have finalizers */
5389 if (!(MONO_CLASS_IS_INTERFACE (klass) || klass->valuetype)) {
5390 MonoMethod *cmethod = NULL;
5392 if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5393 } else if (mono_class_is_ginst (klass)) {
5394 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5396 has_finalize = mono_class_has_finalizer (gklass);
5397 } else if (klass->parent && klass->parent->has_finalize) {
5398 has_finalize = TRUE;
5400 if (klass->parent) {
5402 * Can't search in metadata for a method named Finalize, because that
5403 * ignores overrides.
5405 mono_class_setup_vtable (klass);
5406 if (mono_class_has_failure (klass))
5409 cmethod = klass->vtable [finalize_slot];
5413 g_assert (klass->vtable_size > finalize_slot);
5415 if (klass->parent) {
5416 if (cmethod->is_inflated)
5417 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5418 if (cmethod != default_finalize)
5419 has_finalize = TRUE;
5425 mono_image_lock (klass->image);
5427 if (!klass->has_finalize_inited) {
5428 klass->has_finalize = has_finalize ? 1 : 0;
5430 mono_memory_barrier ();
5431 klass->has_finalize_inited = TRUE;
5434 mono_image_unlock (klass->image);
5436 return klass->has_finalize;
5440 mono_is_corlib_image (MonoImage *image)
5442 return image == mono_defaults.corlib;
5446 * LOCKING: this assumes the loader lock is held
5449 mono_class_setup_mono_type (MonoClass *klass)
5451 const char *name = klass->name;
5452 const char *nspace = klass->name_space;
5453 gboolean is_corlib = mono_is_corlib_image (klass->image);
5455 klass->this_arg.byref = 1;
5456 klass->this_arg.data.klass = klass;
5457 klass->this_arg.type = MONO_TYPE_CLASS;
5458 klass->byval_arg.data.klass = klass;
5459 klass->byval_arg.type = MONO_TYPE_CLASS;
5461 if (is_corlib && !strcmp (nspace, "System")) {
5462 if (!strcmp (name, "ValueType")) {
5464 * do not set the valuetype bit for System.ValueType.
5465 * klass->valuetype = 1;
5467 klass->blittable = TRUE;
5468 } else if (!strcmp (name, "Enum")) {
5470 * do not set the valuetype bit for System.Enum.
5471 * klass->valuetype = 1;
5473 klass->valuetype = 0;
5474 klass->enumtype = 0;
5475 } else if (!strcmp (name, "Object")) {
5476 klass->byval_arg.type = MONO_TYPE_OBJECT;
5477 klass->this_arg.type = MONO_TYPE_OBJECT;
5478 } else if (!strcmp (name, "String")) {
5479 klass->byval_arg.type = MONO_TYPE_STRING;
5480 klass->this_arg.type = MONO_TYPE_STRING;
5481 } else if (!strcmp (name, "TypedReference")) {
5482 klass->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5483 klass->this_arg.type = MONO_TYPE_TYPEDBYREF;
5487 if (klass->valuetype) {
5488 int t = MONO_TYPE_VALUETYPE;
5490 if (is_corlib && !strcmp (nspace, "System")) {
5493 if (!strcmp (name, "Boolean")) {
5494 t = MONO_TYPE_BOOLEAN;
5495 } else if (!strcmp(name, "Byte")) {
5497 klass->blittable = TRUE;
5501 if (!strcmp (name, "Char")) {
5506 if (!strcmp (name, "Double")) {
5508 klass->blittable = TRUE;
5512 if (!strcmp (name, "Int32")) {
5514 klass->blittable = TRUE;
5515 } else if (!strcmp(name, "Int16")) {
5517 klass->blittable = TRUE;
5518 } else if (!strcmp(name, "Int64")) {
5520 klass->blittable = TRUE;
5521 } else if (!strcmp(name, "IntPtr")) {
5523 klass->blittable = TRUE;
5527 if (!strcmp (name, "Single")) {
5529 klass->blittable = TRUE;
5530 } else if (!strcmp(name, "SByte")) {
5532 klass->blittable = TRUE;
5536 if (!strcmp (name, "UInt32")) {
5538 klass->blittable = TRUE;
5539 } else if (!strcmp(name, "UInt16")) {
5541 klass->blittable = TRUE;
5542 } else if (!strcmp(name, "UInt64")) {
5544 klass->blittable = TRUE;
5545 } else if (!strcmp(name, "UIntPtr")) {
5547 klass->blittable = TRUE;
5551 if (!strcmp (name, "TypedReference")) {
5552 t = MONO_TYPE_TYPEDBYREF;
5553 klass->blittable = TRUE;
5557 if (!strcmp (name, "Void")) {
5565 klass->byval_arg.type = (MonoTypeEnum)t;
5566 klass->this_arg.type = (MonoTypeEnum)t;
5569 if (MONO_CLASS_IS_INTERFACE (klass))
5570 klass->interface_id = mono_get_unique_iid (klass);
5575 * COM initialization is delayed until needed.
5576 * However when a [ComImport] attribute is present on a type it will trigger
5577 * the initialization. This is not a problem unless the BCL being executed
5578 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5581 init_com_from_comimport (MonoClass *klass)
5583 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5584 if (mono_security_core_clr_enabled ()) {
5585 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5586 if (!mono_security_core_clr_determine_platform_image (klass->image)) {
5587 /* but it can not be made available for application (i.e. user code) since all COM calls
5588 * are considered native calls. In this case we fail with a TypeLoadException (just like
5589 * Silverlight 2 does */
5590 mono_class_set_type_load_failure (klass, "");
5595 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5597 #endif /*DISABLE_COM*/
5600 * LOCKING: this assumes the loader lock is held
5603 mono_class_setup_parent (MonoClass *klass, MonoClass *parent)
5605 gboolean system_namespace;
5606 gboolean is_corlib = mono_is_corlib_image (klass->image);
5608 system_namespace = !strcmp (klass->name_space, "System") && is_corlib;
5610 /* if root of the hierarchy */
5611 if (system_namespace && !strcmp (klass->name, "Object")) {
5612 klass->parent = NULL;
5613 klass->instance_size = sizeof (MonoObject);
5616 if (!strcmp (klass->name, "<Module>")) {
5617 klass->parent = NULL;
5618 klass->instance_size = 0;
5622 if (!MONO_CLASS_IS_INTERFACE (klass)) {
5623 /* Imported COM Objects always derive from __ComObject. */
5625 if (MONO_CLASS_IS_IMPORT (klass)) {
5626 init_com_from_comimport (klass);
5627 if (parent == mono_defaults.object_class)
5628 parent = mono_class_get_com_object_class ();
5632 /* set the parent to something useful and safe, but mark the type as broken */
5633 parent = mono_defaults.object_class;
5634 mono_class_set_type_load_failure (klass, "");
5638 klass->parent = parent;
5640 if (mono_class_is_ginst (parent) && !parent->name) {
5642 * If the parent is a generic instance, we may get
5643 * called before it is fully initialized, especially
5644 * before it has its name.
5649 #ifndef DISABLE_REMOTING
5650 klass->marshalbyref = parent->marshalbyref;
5651 klass->contextbound = parent->contextbound;
5654 klass->delegate = parent->delegate;
5656 if (MONO_CLASS_IS_IMPORT (klass) || mono_class_is_com_object (parent))
5657 mono_class_set_is_com_object (klass);
5659 if (system_namespace) {
5660 #ifndef DISABLE_REMOTING
5661 if (klass->name [0] == 'M' && !strcmp (klass->name, "MarshalByRefObject"))
5662 klass->marshalbyref = 1;
5664 if (klass->name [0] == 'C' && !strcmp (klass->name, "ContextBoundObject"))
5665 klass->contextbound = 1;
5667 if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate"))
5668 klass->delegate = 1;
5671 if (klass->parent->enumtype || (mono_is_corlib_image (klass->parent->image) && (strcmp (klass->parent->name, "ValueType") == 0) &&
5672 (strcmp (klass->parent->name_space, "System") == 0)))
5673 klass->valuetype = 1;
5674 if (mono_is_corlib_image (klass->parent->image) && ((strcmp (klass->parent->name, "Enum") == 0) && (strcmp (klass->parent->name_space, "System") == 0))) {
5675 klass->valuetype = klass->enumtype = 1;
5677 /*klass->enumtype = klass->parent->enumtype; */
5679 /* initialize com types if COM interfaces are present */
5681 if (MONO_CLASS_IS_IMPORT (klass))
5682 init_com_from_comimport (klass);
5684 klass->parent = NULL;
5690 * mono_class_setup_supertypes:
5693 * Build the data structure needed to make fast type checks work.
5694 * This currently sets two fields in @class:
5695 * - idepth: distance between @class and System.Object in the type
5697 * - supertypes: array of classes: each element has a class in the hierarchy
5698 * starting from @class up to System.Object
5700 * LOCKING: Acquires the loader lock.
5703 mono_class_setup_supertypes (MonoClass *klass)
5706 MonoClass **supertypes;
5708 mono_atomic_load_acquire (supertypes, MonoClass **, &klass->supertypes);
5712 if (klass->parent && !klass->parent->supertypes)
5713 mono_class_setup_supertypes (klass->parent);
5715 idepth = klass->parent->idepth + 1;
5719 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, idepth);
5720 supertypes = (MonoClass **)mono_class_alloc0 (klass, sizeof (MonoClass *) * ms);
5722 if (klass->parent) {
5723 CHECKED_METADATA_WRITE_PTR ( supertypes [idepth - 1] , klass );
5726 for (supertype_idx = 0; supertype_idx < klass->parent->idepth; supertype_idx++)
5727 CHECKED_METADATA_WRITE_PTR ( supertypes [supertype_idx] , klass->parent->supertypes [supertype_idx] );
5729 CHECKED_METADATA_WRITE_PTR ( supertypes [0] , klass );
5732 mono_memory_barrier ();
5734 mono_loader_lock ();
5735 klass->idepth = idepth;
5736 /* Needed so idepth is visible before supertypes is set */
5737 mono_memory_barrier ();
5738 klass->supertypes = supertypes;
5739 mono_loader_unlock ();
5743 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5745 MonoClass *gtd = (MonoClass*)user_data;
5746 /* Only try to fix generic instances of @gtd */
5747 if (mono_class_get_generic_class (gclass)->container_class != gtd)
5750 /* Check if the generic instance has no parent. */
5751 if (gtd->parent && !gclass->parent)
5752 mono_generic_class_setup_parent (gclass, gtd);
5758 mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char *msg)
5760 mono_class_set_type_load_failure (klass, "%s", msg);
5761 mono_error_set_type_load_class (error, klass, "%s", msg);
5765 * mono_class_create_from_typedef:
5766 * @image: image where the token is valid
5767 * @type_token: typedef token
5768 * @error: used to return any error found while creating the type
5770 * Create the MonoClass* representing the specified type token.
5771 * @type_token must be a TypeDef token.
5773 * FIXME: don't return NULL on failure, just the the caller figure it out.
5776 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5778 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5779 MonoClass *klass, *parent = NULL;
5780 guint32 cols [MONO_TYPEDEF_SIZE];
5781 guint32 cols_next [MONO_TYPEDEF_SIZE];
5782 guint tidx = mono_metadata_token_index (type_token);
5783 MonoGenericContext *context = NULL;
5784 const char *name, *nspace;
5786 MonoClass **interfaces;
5787 guint32 field_last, method_last;
5788 guint32 nesting_tokeen;
5790 mono_error_init (error);
5792 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5793 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5797 mono_loader_lock ();
5799 if ((klass = (MonoClass *)mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5800 mono_loader_unlock ();
5804 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5806 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5807 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5809 if (mono_metadata_has_generic_params (image, type_token)) {
5810 klass = mono_image_alloc0 (image, sizeof (MonoClassGtd));
5811 klass->class_kind = MONO_CLASS_GTD;
5812 classes_size += sizeof (MonoClassGtd);
5815 klass = mono_image_alloc0 (image, sizeof (MonoClassDef));
5816 klass->class_kind = MONO_CLASS_DEF;
5817 classes_size += sizeof (MonoClassDef);
5822 klass->name_space = nspace;
5824 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5826 klass->image = image;
5827 klass->type_token = type_token;
5828 mono_class_set_flags (klass, cols [MONO_TYPEDEF_FLAGS]);
5830 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
5833 * Check whether we're a generic type definition.
5835 if (mono_class_is_gtd (klass)) {
5836 MonoGenericContainer *generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
5837 generic_container->owner.klass = klass;
5838 generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
5839 context = &generic_container->context;
5840 mono_class_set_generic_container (klass, generic_container);
5841 enable_gclass_recording ();
5844 if (cols [MONO_TYPEDEF_EXTENDS]) {
5846 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5848 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5849 /*WARNING: this must satisfy mono_metadata_type_hash*/
5850 klass->this_arg.byref = 1;
5851 klass->this_arg.data.klass = klass;
5852 klass->this_arg.type = MONO_TYPE_CLASS;
5853 klass->byval_arg.data.klass = klass;
5854 klass->byval_arg.type = MONO_TYPE_CLASS;
5856 parent = mono_class_get_checked (image, parent_token, error);
5857 if (parent && context) /* Always inflate */
5858 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5860 if (parent == NULL) {
5861 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5862 goto parent_failure;
5865 for (tmp = parent; tmp; tmp = tmp->parent) {
5867 mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
5868 goto parent_failure;
5870 if (mono_class_is_gtd (klass) && mono_class_is_ginst (tmp) && mono_class_get_generic_class (tmp)->container_class == klass) {
5871 mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
5872 goto parent_failure;
5877 mono_class_setup_parent (klass, parent);
5879 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5880 mono_class_setup_mono_type (klass);
5882 if (mono_class_is_gtd (klass))
5883 disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
5886 * This might access klass->byval_arg for recursion generated by generic constraints,
5887 * so it has to come after setup_mono_type ().
5889 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5890 klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5891 if (!mono_error_ok (error)) {
5892 /*FIXME implement a mono_class_set_failure_from_mono_error */
5893 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5894 mono_loader_unlock ();
5895 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5900 if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5904 if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5908 klass->cast_class = klass->element_class = klass;
5910 if (!klass->enumtype) {
5911 if (!mono_metadata_interfaces_from_typedef_full (
5912 image, type_token, &interfaces, &icount, FALSE, context, error)){
5914 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5915 mono_loader_unlock ();
5916 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5920 /* This is required now that it is possible for more than 2^16 interfaces to exist. */
5921 g_assert(icount <= 65535);
5923 klass->interfaces = interfaces;
5924 klass->interface_count = icount;
5925 klass->interfaces_inited = 1;
5928 /*g_print ("Load class %s\n", name);*/
5931 * Compute the field and method lists
5933 int first_field_idx = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5934 mono_class_set_first_field_idx (klass, first_field_idx);
5935 int first_method_idx = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5936 mono_class_set_first_method_idx (klass, first_method_idx);
5938 if (tt->rows > tidx){
5939 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5940 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5941 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5943 field_last = image->tables [MONO_TABLE_FIELD].rows;
5944 method_last = image->tables [MONO_TABLE_METHOD].rows;
5947 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5948 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5949 mono_class_set_field_count (klass, field_last - first_field_idx);
5950 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5951 mono_class_set_method_count (klass, method_last - first_method_idx);
5953 /* reserve space to store vector pointer in arrays */
5954 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5955 klass->instance_size += 2 * sizeof (gpointer);
5956 g_assert (mono_class_get_field_count (klass) == 0);
5959 if (klass->enumtype) {
5960 MonoType *enum_basetype = mono_class_find_enum_basetype (klass, error);
5961 if (!enum_basetype) {
5962 /*set it to a default value as the whole runtime can't handle this to be null*/
5963 klass->cast_class = klass->element_class = mono_defaults.int32_class;
5964 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5965 mono_loader_unlock ();
5966 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5969 klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
5973 * If we're a generic type definition, load the constraints.
5974 * We must do this after the class has been constructed to make certain recursive scenarios
5977 if (mono_class_is_gtd (klass) && !mono_metadata_load_generic_param_constraints_checked (image, type_token, mono_class_get_generic_container (klass), error)) {
5978 mono_class_set_type_load_failure (klass, "Could not load generic parameter constrains due to %s", mono_error_get_message (error));
5979 mono_loader_unlock ();
5980 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5984 if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5985 if (!strncmp (name, "Vector", 6))
5986 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");
5987 } else if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "System.Numerics") && !strcmp (nspace, "System.Numerics")) {
5988 if (!strcmp (name, "Vector2") || !strcmp (name, "Vector3") || !strcmp (name, "Vector4"))
5989 klass->simd_type = 1;
5990 } else if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "System.Numerics.Vectors") && !strcmp (nspace, "System.Numerics")) {
5991 if (!strcmp (name, "Vector`1"))
5992 klass->simd_type = 1;
5995 mono_loader_unlock ();
5997 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6002 mono_class_setup_mono_type (klass);
6003 mono_loader_unlock ();
6004 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
6008 /** Is klass a Nullable<T> ginst? */
6010 mono_class_is_nullable (MonoClass *klass)
6012 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
6013 return gklass && gklass->container_class == mono_defaults.generic_nullable_class;
6017 /** if klass is T? return T */
6019 mono_class_get_nullable_param (MonoClass *klass)
6021 g_assert (mono_class_is_nullable (klass));
6022 return mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
6026 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
6030 MonoGenericClass *gclass = mono_class_get_generic_class (klass);
6032 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
6033 if (!mono_error_ok (&error)) {
6034 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
6035 klass->parent = mono_defaults.object_class;
6036 mono_class_set_type_load_failure (klass, "Parent is a generic type instantiation that failed due to: %s", mono_error_get_message (&error));
6037 mono_error_cleanup (&error);
6041 mono_class_setup_parent (klass, klass->parent);
6043 if (klass->enumtype) {
6044 klass->cast_class = gtd->cast_class;
6045 klass->element_class = gtd->element_class;
6051 * Create the `MonoClass' for an instantiation of a generic type.
6052 * We only do this if we actually need it.
6055 mono_generic_class_get_class (MonoGenericClass *gclass)
6057 MonoClass *klass, *gklass;
6059 if (gclass->cached_class)
6060 return gclass->cached_class;
6062 mono_loader_lock ();
6063 if (gclass->cached_class) {
6064 mono_loader_unlock ();
6065 return gclass->cached_class;
6068 klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClassGenericInst));
6070 gklass = gclass->container_class;
6072 if (record_gclass_instantiation > 0)
6073 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
6075 if (gklass->nested_in) {
6076 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
6077 klass->nested_in = gklass->nested_in;
6080 klass->name = gklass->name;
6081 klass->name_space = gklass->name_space;
6083 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6085 klass->image = gklass->image;
6086 klass->type_token = gklass->type_token;
6088 klass->class_kind = MONO_CLASS_GINST;
6090 ((MonoClassGenericInst*)klass)->generic_class = gclass;
6092 klass->byval_arg.type = MONO_TYPE_GENERICINST;
6093 klass->this_arg.type = klass->byval_arg.type;
6094 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
6095 klass->this_arg.byref = TRUE;
6096 klass->enumtype = gklass->enumtype;
6097 klass->valuetype = gklass->valuetype;
6098 klass->simd_type = gklass->simd_type;
6100 klass->cast_class = klass->element_class = klass;
6102 if (mono_class_is_nullable (klass))
6103 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
6106 * We're not interested in the nested classes of a generic instance.
6107 * We use the generic type definition to look for nested classes.
6110 mono_generic_class_setup_parent (klass, gklass);
6112 if (gclass->is_dynamic) {
6114 * 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.
6115 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
6116 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
6118 if (!gklass->wastypebuilder)
6121 mono_class_setup_supertypes (klass);
6123 if (klass->enumtype) {
6125 * For enums, gklass->fields might not been set, but instance_size etc. is
6126 * already set in mono_reflection_create_internal_class (). For non-enums,
6127 * these will be computed normally in mono_class_layout_fields ().
6129 klass->instance_size = gklass->instance_size;
6130 klass->sizes.class_size = gklass->sizes.class_size;
6131 mono_memory_barrier ();
6132 klass->size_inited = 1;
6136 mono_memory_barrier ();
6137 gclass->cached_class = klass;
6139 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6141 ++class_ginst_count;
6142 inflated_classes_size += sizeof (MonoClassGenericInst);
6144 mono_loader_unlock ();
6150 get_image_for_container (MonoGenericContainer *container)
6153 if (container->is_anonymous) {
6154 result = container->owner.image;
6157 if (container->is_method) {
6158 MonoMethod *method = container->owner.method;
6159 g_assert_checked (method);
6160 klass = method->klass;
6162 klass = container->owner.klass;
6164 g_assert_checked (klass);
6165 result = klass->image;
6172 get_image_for_generic_param (MonoGenericParam *param)
6174 MonoGenericContainer *container = mono_generic_param_owner (param);
6175 g_assert_checked (container);
6176 return get_image_for_container (container);
6179 // Make a string in the designated image consisting of a single integer.
6180 #define INT_STRING_SIZE 16
6182 make_generic_name_string (MonoImage *image, int num)
6184 char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
6185 g_snprintf (name, INT_STRING_SIZE, "%d", num);
6189 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
6190 // pinfo is derived from param by the caller for us.
6192 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
6194 MonoClass *klass, **ptr;
6196 MonoGenericContainer *container = mono_generic_param_owner (param);
6197 g_assert_checked (container);
6199 MonoImage *image = get_image_for_container (container);
6200 gboolean is_mvar = container->is_method;
6201 gboolean is_anonymous = container->is_anonymous;
6203 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassGenericParam));
6204 klass->class_kind = MONO_CLASS_GPARAM;
6205 classes_size += sizeof (MonoClassGenericParam);
6206 ++class_gparam_count;
6209 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
6211 int n = mono_generic_param_num (param);
6212 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
6216 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , "" );
6217 } else if (is_mvar) {
6218 MonoMethod *omethod = container->owner.method;
6219 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
6221 MonoClass *oklass = container->owner.klass;
6222 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
6225 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6227 // Count non-NULL items in pinfo->constraints
6230 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6234 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6235 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
6237 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
6238 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
6240 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
6243 if (count - pos > 0) {
6244 klass->interface_count = count - pos;
6245 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
6246 klass->interfaces_inited = TRUE;
6247 for (i = pos; i < count; i++)
6248 CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
6251 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
6253 klass->inited = TRUE;
6254 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class , klass );
6255 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
6257 klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6258 klass->this_arg.type = klass->byval_arg.type;
6259 CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param , param );
6260 CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
6261 klass->this_arg.byref = TRUE;
6263 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6264 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6266 /*Init these fields to sane values*/
6267 klass->min_align = 1;
6269 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6270 * constrained to, the JIT depends on this.
6272 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6273 mono_memory_barrier ();
6274 klass->size_inited = 1;
6276 mono_class_setup_supertypes (klass);
6278 if (count - pos > 0) {
6279 mono_class_setup_vtable (klass->parent);
6280 if (mono_class_has_failure (klass->parent))
6281 mono_class_set_type_load_failure (klass, "Failed to setup parent interfaces");
6283 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6289 #define FAST_CACHE_SIZE 16
6292 * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6293 * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6294 * we cache the MonoClasses.
6295 * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6296 * LOCKING: Takes the image lock depending on @take_lock.
6299 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6301 int n = mono_generic_param_num (param);
6302 MonoImage *image = get_image_for_generic_param (param);
6303 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6304 MonoClass *klass = NULL;
6309 // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6310 // For high numbers or constraints we have to use pointer hashes.
6311 if (param->gshared_constraint) {
6312 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6315 mono_image_lock (image);
6316 klass = (MonoClass *)g_hash_table_lookup (ht, param);
6318 mono_image_unlock (image);
6323 if (n < FAST_CACHE_SIZE) {
6325 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6327 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6329 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6332 mono_image_lock (image);
6333 klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6335 mono_image_unlock (image);
6342 * LOCKING: Image lock (param->image) must be held
6345 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6347 int n = mono_generic_param_num (param);
6348 MonoImage *image = get_image_for_generic_param (param);
6349 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6353 if (param->gshared_constraint) {
6354 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6356 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6357 mono_memory_barrier ();
6359 image->mvar_cache_constrained = ht;
6361 image->var_cache_constrained = ht;
6363 g_hash_table_insert (ht, param, klass);
6364 } else if (n < FAST_CACHE_SIZE) {
6366 /* Requires locking to avoid droping an already published class */
6367 if (!image->mvar_cache_fast)
6368 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6369 image->mvar_cache_fast [n] = klass;
6371 if (!image->var_cache_fast)
6372 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6373 image->var_cache_fast [n] = klass;
6376 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6378 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6380 ht = g_hash_table_new (NULL, NULL);
6381 mono_memory_barrier ();
6383 image->mvar_cache_slow = ht;
6385 image->var_cache_slow = ht;
6388 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6393 * LOCKING: Acquires the image lock (@image).
6396 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6398 MonoImage *image = get_image_for_generic_param (param);
6399 MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6400 MonoClass *klass, *klass2;
6402 // If a klass already exists for this object and is cached, return it.
6403 if (pinfo) // Non-anonymous
6404 klass = pinfo->pklass;
6406 klass = get_anon_gparam_class (param, TRUE);
6411 // Create a new klass
6412 klass = make_generic_param_class (param, pinfo);
6414 // Now we need to cache the klass we created.
6415 // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6416 // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6417 // and allow our newly-created klass object to just leak.
6418 mono_memory_barrier ();
6420 mono_image_lock (image);
6422 // Here "klass2" refers to the klass potentially created by the other thread.
6423 if (pinfo) // Repeat check from above
6424 klass2 = pinfo->pklass;
6426 klass2 = get_anon_gparam_class (param, FALSE);
6433 pinfo->pklass = klass;
6435 set_anon_gparam_class (param, klass);
6437 mono_image_unlock (image);
6439 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6441 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED); // Alert profiler about botched class create
6443 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6449 * mono_class_from_generic_parameter:
6450 * @param: Parameter to find/construct a class for.
6451 * @arg2: Is ignored.
6452 * @arg3: Is ignored.
6455 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6457 return mono_class_from_generic_parameter_internal (param);
6462 mono_ptr_class_get (MonoType *type)
6465 MonoClass *el_class;
6469 el_class = mono_class_from_mono_type (type);
6470 image = el_class->image;
6472 mono_image_lock (image);
6473 if (image->ptr_cache) {
6474 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6475 mono_image_unlock (image);
6479 mono_image_unlock (image);
6481 result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassPointer));
6483 classes_size += sizeof (MonoClassPointer);
6484 ++class_pointer_count;
6486 result->parent = NULL; /* no parent for PTR types */
6487 result->name_space = el_class->name_space;
6488 name = g_strdup_printf ("%s*", el_class->name);
6489 result->name = mono_image_strdup (image, name);
6490 result->class_kind = MONO_CLASS_POINTER;
6493 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6495 result->image = el_class->image;
6496 result->inited = TRUE;
6497 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6498 result->cast_class = result->element_class = el_class;
6499 result->blittable = TRUE;
6501 result->byval_arg.type = MONO_TYPE_PTR;
6502 result->this_arg.type = result->byval_arg.type;
6503 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6504 result->this_arg.byref = TRUE;
6506 mono_class_setup_supertypes (result);
6508 mono_image_lock (image);
6509 if (image->ptr_cache) {
6511 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6512 mono_image_unlock (image);
6513 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6517 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6519 g_hash_table_insert (image->ptr_cache, el_class, result);
6520 mono_image_unlock (image);
6522 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6528 mono_fnptr_class_get (MonoMethodSignature *sig)
6531 static GHashTable *ptr_hash = NULL;
6533 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6535 mono_loader_lock ();
6538 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6540 if ((result = (MonoClass *)g_hash_table_lookup (ptr_hash, sig))) {
6541 mono_loader_unlock ();
6544 result = g_new0 (MonoClass, 1);
6546 classes_size += sizeof (MonoClassPointer);
6547 ++class_pointer_count;
6549 result->parent = NULL; /* no parent for PTR types */
6550 result->name_space = "System";
6551 result->name = "MonoFNPtrFakeClass";
6552 result->class_kind = MONO_CLASS_POINTER;
6554 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6556 result->image = mono_defaults.corlib; /* need to fix... */
6557 result->inited = TRUE;
6558 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6559 result->cast_class = result->element_class = result;
6560 result->blittable = TRUE;
6562 result->byval_arg.type = MONO_TYPE_FNPTR;
6563 result->this_arg.type = result->byval_arg.type;
6564 result->this_arg.data.method = result->byval_arg.data.method = sig;
6565 result->this_arg.byref = TRUE;
6566 result->blittable = TRUE;
6568 mono_class_setup_supertypes (result);
6570 g_hash_table_insert (ptr_hash, sig, result);
6572 mono_loader_unlock ();
6574 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6580 * mono_class_from_mono_type:
6581 * @type: describes the type to return
6583 * This returns a MonoClass for the specified MonoType, the value is never NULL.
6586 mono_class_from_mono_type (MonoType *type)
6588 switch (type->type) {
6589 case MONO_TYPE_OBJECT:
6590 return type->data.klass? type->data.klass: mono_defaults.object_class;
6591 case MONO_TYPE_VOID:
6592 return type->data.klass? type->data.klass: mono_defaults.void_class;
6593 case MONO_TYPE_BOOLEAN:
6594 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6595 case MONO_TYPE_CHAR:
6596 return type->data.klass? type->data.klass: mono_defaults.char_class;
6598 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6600 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6602 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6604 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6606 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6608 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6610 return type->data.klass? type->data.klass: mono_defaults.int_class;
6612 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6614 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6616 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6618 return type->data.klass? type->data.klass: mono_defaults.single_class;
6620 return type->data.klass? type->data.klass: mono_defaults.double_class;
6621 case MONO_TYPE_STRING:
6622 return type->data.klass? type->data.klass: mono_defaults.string_class;
6623 case MONO_TYPE_TYPEDBYREF:
6624 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6625 case MONO_TYPE_ARRAY:
6626 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6628 return mono_ptr_class_get (type->data.type);
6629 case MONO_TYPE_FNPTR:
6630 return mono_fnptr_class_get (type->data.method);
6631 case MONO_TYPE_SZARRAY:
6632 return mono_array_class_get (type->data.klass, 1);
6633 case MONO_TYPE_CLASS:
6634 case MONO_TYPE_VALUETYPE:
6635 return type->data.klass;
6636 case MONO_TYPE_GENERICINST:
6637 return mono_generic_class_get_class (type->data.generic_class);
6638 case MONO_TYPE_MVAR:
6640 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6642 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6643 g_assert_not_reached ();
6646 // Yes, this returns NULL, even if it is documented as not doing so, but there
6647 // is no way for the code to make it this far, due to the assert above.
6652 * mono_type_retrieve_from_typespec
6653 * @image: context where the image is created
6654 * @type_spec: typespec token
6655 * @context: the generic context used to evaluate generic instantiations in
6658 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6660 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6662 *did_inflate = FALSE;
6667 if (context && (context->class_inst || context->method_inst)) {
6668 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6670 if (!mono_error_ok (error)) {
6676 *did_inflate = TRUE;
6683 * mono_class_create_from_typespec
6684 * @image: context where the image is created
6685 * @type_spec: typespec token
6686 * @context: the generic context used to evaluate generic instantiations in
6689 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6692 gboolean inflated = FALSE;
6693 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6694 return_val_if_nok (error, NULL);
6695 ret = mono_class_from_mono_type (t);
6697 mono_metadata_free_type (t);
6702 * mono_bounded_array_class_get:
6703 * @element_class: element class
6704 * @rank: the dimension of the array class
6705 * @bounded: whenever the array has non-zero bounds
6707 * Returns: A class object describing the array with element type @element_type and
6711 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6715 MonoClass *parent = NULL;
6716 GSList *list, *rootlist = NULL;
6720 g_assert (rank <= 255);
6723 /* bounded only matters for one-dimensional arrays */
6726 image = eclass->image;
6728 if (rank == 1 && !bounded) {
6730 * This case is very frequent not just during compilation because of calls
6731 * from mono_class_from_mono_type (), mono_array_new (),
6732 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6734 mono_os_mutex_lock (&image->szarray_cache_lock);
6735 if (!image->szarray_cache)
6736 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6737 klass = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6738 mono_os_mutex_unlock (&image->szarray_cache_lock);
6742 mono_loader_lock ();
6744 mono_loader_lock ();
6746 if (!image->array_cache)
6747 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6749 if ((rootlist = list = (GSList *)g_hash_table_lookup (image->array_cache, eclass))) {
6750 for (; list; list = list->next) {
6751 klass = (MonoClass *)list->data;
6752 if ((klass->rank == rank) && (klass->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6753 mono_loader_unlock ();
6760 parent = mono_defaults.array_class;
6761 if (!parent->inited)
6762 mono_class_init (parent);
6764 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassArray));
6766 klass->image = image;
6767 klass->name_space = eclass->name_space;
6768 klass->class_kind = MONO_CLASS_ARRAY;
6770 nsize = strlen (eclass->name);
6771 name = (char *)g_malloc (nsize + 2 + rank + 1);
6772 memcpy (name, eclass->name, nsize);
6775 memset (name + nsize + 1, ',', rank - 1);
6777 name [nsize + rank] = '*';
6778 name [nsize + rank + bounded] = ']';
6779 name [nsize + rank + bounded + 1] = 0;
6780 klass->name = mono_image_strdup (image, name);
6783 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6785 classes_size += sizeof (MonoClassArray);
6786 ++class_array_count;
6788 klass->type_token = 0;
6789 klass->parent = parent;
6790 klass->instance_size = mono_class_instance_size (klass->parent);
6792 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6793 /*Arrays of those two types are invalid.*/
6794 MonoError prepared_error;
6795 mono_error_init (&prepared_error);
6796 mono_error_set_invalid_program (&prepared_error, "Arrays of void or System.TypedReference types are invalid.");
6797 mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6798 mono_error_cleanup (&prepared_error);
6799 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6800 guint32 ref_info_handle = mono_class_get_ref_info_handle (eclass);
6801 if (!ref_info_handle || eclass->wastypebuilder) {
6802 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6803 g_assert (ref_info_handle && !eclass->wastypebuilder);
6805 /* element_size -1 is ok as this is not an instantitable type*/
6806 klass->sizes.element_size = -1;
6808 klass->sizes.element_size = mono_class_array_element_size (eclass);
6810 mono_class_setup_supertypes (klass);
6812 if (mono_class_is_ginst (eclass))
6813 mono_class_init (eclass);
6814 if (!eclass->size_inited)
6815 mono_class_setup_fields (eclass);
6816 mono_class_set_type_load_failure_causedby_class (klass, eclass, "Could not load array element type");
6817 /*FIXME we fail the array type, but we have to let other fields be set.*/
6819 klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6823 if (eclass->enumtype)
6824 klass->cast_class = eclass->element_class;
6826 klass->cast_class = eclass;
6828 switch (klass->cast_class->byval_arg.type) {
6830 klass->cast_class = mono_defaults.byte_class;
6833 klass->cast_class = mono_defaults.int16_class;
6836 #if SIZEOF_VOID_P == 4
6840 klass->cast_class = mono_defaults.int32_class;
6843 #if SIZEOF_VOID_P == 8
6847 klass->cast_class = mono_defaults.int64_class;
6853 klass->element_class = eclass;
6855 if ((rank > 1) || bounded) {
6856 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6857 klass->byval_arg.type = MONO_TYPE_ARRAY;
6858 klass->byval_arg.data.array = at;
6859 at->eklass = eclass;
6861 /* FIXME: complete.... */
6863 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6864 klass->byval_arg.data.klass = eclass;
6866 klass->this_arg = klass->byval_arg;
6867 klass->this_arg.byref = 1;
6869 //WTF was this? it's wrong
6870 // klass->generic_container = eclass->generic_container;
6872 if (rank == 1 && !bounded) {
6873 MonoClass *prev_class;
6875 mono_os_mutex_lock (&image->szarray_cache_lock);
6876 prev_class = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6878 /* Someone got in before us */
6881 g_hash_table_insert (image->szarray_cache, eclass, klass);
6882 mono_os_mutex_unlock (&image->szarray_cache_lock);
6884 list = g_slist_append (rootlist, klass);
6885 g_hash_table_insert (image->array_cache, eclass, list);
6888 mono_loader_unlock ();
6890 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6896 * mono_array_class_get:
6897 * @element_class: element class
6898 * @rank: the dimension of the array class
6900 * Returns: A class object describing the array with element type @element_type and
6904 mono_array_class_get (MonoClass *eclass, guint32 rank)
6906 return mono_bounded_array_class_get (eclass, rank, FALSE);
6910 * mono_class_instance_size:
6913 * Use to get the size of a class in bytes.
6915 * Returns: The size of an object instance
6918 mono_class_instance_size (MonoClass *klass)
6920 if (!klass->size_inited)
6921 mono_class_init (klass);
6923 return klass->instance_size;
6927 * mono_class_min_align:
6930 * Use to get the computed minimum alignment requirements for the specified class.
6932 * Returns: minimum alignment requirements
6935 mono_class_min_align (MonoClass *klass)
6937 if (!klass->size_inited)
6938 mono_class_init (klass);
6940 return klass->min_align;
6944 * mono_class_value_size:
6947 * This function is used for value types, and return the
6948 * space and the alignment to store that kind of value object.
6950 * Returns: the size of a value of kind @klass
6953 mono_class_value_size (MonoClass *klass, guint32 *align)
6957 /* fixme: check disable, because we still have external revereces to
6958 * mscorlib and Dummy Objects
6960 /*g_assert (klass->valuetype);*/
6962 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6965 *align = klass->min_align;
6971 * mono_class_data_size:
6974 * Returns: The size of the static class data
6977 mono_class_data_size (MonoClass *klass)
6980 mono_class_init (klass);
6981 /* This can happen with dynamically created types */
6982 if (!klass->fields_inited)
6983 mono_class_setup_fields (klass);
6985 /* in arrays, sizes.class_size is unioned with element_size
6986 * and arrays have no static fields
6990 return klass->sizes.class_size;
6994 * Auxiliary routine to mono_class_get_field
6996 * Takes a field index instead of a field token.
6998 static MonoClassField *
6999 mono_class_get_field_idx (MonoClass *klass, int idx)
7001 mono_class_setup_fields (klass);
7002 if (mono_class_has_failure (klass))
7006 int first_field_idx = mono_class_get_first_field_idx (klass);
7007 int fcount = mono_class_get_field_count (klass);
7008 if (klass->image->uncompressed_metadata) {
7010 * first_field_idx points to the FieldPtr table, while idx points into the
7011 * Field table, so we have to do a search.
7013 /*FIXME this is broken for types with multiple fields with the same name.*/
7014 const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
7017 for (i = 0; i < fcount; ++i)
7018 if (mono_field_get_name (&klass->fields [i]) == name)
7019 return &klass->fields [i];
7020 g_assert_not_reached ();
7023 if ((idx >= first_field_idx) && (idx < first_field_idx + fcount)){
7024 return &klass->fields [idx - first_field_idx];
7028 klass = klass->parent;
7034 * mono_class_get_field:
7035 * @class: the class to lookup the field.
7036 * @field_token: the field token
7038 * Returns: A MonoClassField representing the type and offset of
7039 * the field, or a NULL value if the field does not belong to this
7043 mono_class_get_field (MonoClass *klass, guint32 field_token)
7045 int idx = mono_metadata_token_index (field_token);
7047 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
7049 return mono_class_get_field_idx (klass, idx - 1);
7053 * mono_class_get_field_from_name:
7054 * @klass: the class to lookup the field.
7055 * @name: the field name
7057 * Search the class @klass and it's parents for a field with the name @name.
7059 * Returns: The MonoClassField pointer of the named field or NULL
7062 mono_class_get_field_from_name (MonoClass *klass, const char *name)
7064 return mono_class_get_field_from_name_full (klass, name, NULL);
7068 * mono_class_get_field_from_name_full:
7069 * @klass: the class to lookup the field.
7070 * @name: the field name
7071 * @type: the type of the fields. This optional.
7073 * Search the class @klass and it's parents for a field with the name @name and type @type.
7075 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
7076 * of its generic type definition.
7078 * Returns: The MonoClassField pointer of the named field or NULL
7081 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
7085 mono_class_setup_fields (klass);
7086 if (mono_class_has_failure (klass))
7090 int fcount = mono_class_get_field_count (klass);
7091 for (i = 0; i < fcount; ++i) {
7092 MonoClassField *field = &klass->fields [i];
7094 if (strcmp (name, mono_field_get_name (field)) != 0)
7098 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
7099 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
7104 klass = klass->parent;
7110 * mono_class_get_field_token:
7111 * @field: the field we need the token of
7113 * Get the token of a field. Note that the tokesn is only valid for the image
7114 * the field was loaded from. Don't use this function for fields in dynamic types.
7116 * Returns: The token representing the field in the image it was loaded from.
7119 mono_class_get_field_token (MonoClassField *field)
7121 MonoClass *klass = field->parent;
7124 mono_class_setup_fields (klass);
7129 int first_field_idx = mono_class_get_first_field_idx (klass);
7130 int fcount = mono_class_get_field_count (klass);
7131 for (i = 0; i < fcount; ++i) {
7132 if (&klass->fields [i] == field) {
7133 int idx = first_field_idx + i + 1;
7135 if (klass->image->uncompressed_metadata)
7136 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
7137 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
7140 klass = klass->parent;
7143 g_assert_not_reached ();
7148 mono_field_get_index (MonoClassField *field)
7150 int index = field - field->parent->fields;
7151 g_assert (index >= 0 && index < mono_class_get_field_count (field->parent));
7157 * mono_class_get_field_default_value:
7159 * Return the default value of the field as a pointer into the metadata blob.
7162 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
7165 guint32 constant_cols [MONO_CONSTANT_SIZE];
7167 MonoClass *klass = field->parent;
7169 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7171 MonoClassExt *ext = mono_class_get_ext (klass);
7172 if (!ext || !ext->field_def_values) {
7173 MonoFieldDefaultValue *def_values;
7175 mono_class_alloc_ext (klass);
7176 ext = mono_class_get_ext (klass);
7178 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
7180 mono_image_lock (klass->image);
7181 mono_memory_barrier ();
7182 if (!ext->field_def_values)
7183 ext->field_def_values = def_values;
7184 mono_image_unlock (klass->image);
7187 field_index = mono_field_get_index (field);
7189 if (!ext->field_def_values [field_index].data) {
7190 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7194 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7196 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7197 ext->field_def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7198 ext->field_def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7201 *def_type = ext->field_def_values [field_index].def_type;
7202 return ext->field_def_values [field_index].data;
7206 mono_property_get_index (MonoProperty *prop)
7208 MonoClassExt *ext = mono_class_get_ext (prop->parent);
7209 int index = prop - ext->properties;
7211 g_assert (index >= 0 && index < ext->property.count);
7217 * mono_class_get_property_default_value:
7219 * Return the default value of the field as a pointer into the metadata blob.
7222 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7225 guint32 constant_cols [MONO_CONSTANT_SIZE];
7226 MonoClass *klass = property->parent;
7228 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7230 * We don't cache here because it is not used by C# so it's quite rare, but
7231 * we still do the lookup in klass->ext because that is where the data
7232 * is stored for dynamic assemblies.
7235 if (image_is_dynamic (klass->image)) {
7236 MonoClassExt *ext = mono_class_get_ext (klass);
7237 int prop_index = mono_property_get_index (property);
7238 if (ext->prop_def_values && ext->prop_def_values [prop_index].data) {
7239 *def_type = ext->prop_def_values [prop_index].def_type;
7240 return ext->prop_def_values [prop_index].data;
7244 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7248 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7249 *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7250 return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7254 mono_class_get_event_token (MonoEvent *event)
7256 MonoClass *klass = event->parent;
7260 MonoClassExt *ext = mono_class_get_ext (klass);
7262 for (i = 0; i < ext->event.count; ++i) {
7263 if (&ext->events [i] == event)
7264 return mono_metadata_make_token (MONO_TABLE_EVENT, ext->event.first + i + 1);
7267 klass = klass->parent;
7270 g_assert_not_reached ();
7275 * mono_class_get_property_from_name:
7277 * @name: name of the property to lookup in the specified class
7279 * Use this method to lookup a property in a class
7280 * Returns: the MonoProperty with the given name, or NULL if the property
7281 * does not exist on the @klass.
7284 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7288 gpointer iter = NULL;
7289 while ((p = mono_class_get_properties (klass, &iter))) {
7290 if (! strcmp (name, p->name))
7293 klass = klass->parent;
7299 * mono_class_get_property_token:
7300 * @prop: MonoProperty to query
7302 * Returns: The ECMA token for the specified property.
7305 mono_class_get_property_token (MonoProperty *prop)
7307 MonoClass *klass = prop->parent;
7311 gpointer iter = NULL;
7312 MonoClassExt *ext = mono_class_get_ext (klass);
7313 while ((p = mono_class_get_properties (klass, &iter))) {
7314 if (&ext->properties [i] == prop)
7315 return mono_metadata_make_token (MONO_TABLE_PROPERTY, ext->property.first + i + 1);
7319 klass = klass->parent;
7322 g_assert_not_reached ();
7327 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7329 const char *name, *nspace;
7330 if (image_is_dynamic (image))
7331 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7333 switch (type_token & 0xff000000){
7334 case MONO_TOKEN_TYPE_DEF: {
7335 guint32 cols [MONO_TYPEDEF_SIZE];
7336 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7337 guint tidx = mono_metadata_token_index (type_token);
7339 if (tidx > tt->rows)
7340 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7342 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7343 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7344 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7345 if (strlen (nspace) == 0)
7346 return g_strdup_printf ("%s", name);
7348 return g_strdup_printf ("%s.%s", nspace, name);
7351 case MONO_TOKEN_TYPE_REF: {
7353 guint32 cols [MONO_TYPEREF_SIZE];
7354 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7355 guint tidx = mono_metadata_token_index (type_token);
7358 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7360 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7361 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7362 mono_error_cleanup (&error);
7366 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7367 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7368 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7369 if (strlen (nspace) == 0)
7370 return g_strdup_printf ("%s", name);
7372 return g_strdup_printf ("%s.%s", nspace, name);
7375 case MONO_TOKEN_TYPE_SPEC:
7376 return g_strdup_printf ("Typespec 0x%08x", type_token);
7378 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7383 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7385 if (image_is_dynamic (image))
7386 return g_strdup_printf ("DynamicAssembly %s", image->name);
7388 switch (type_token & 0xff000000){
7389 case MONO_TOKEN_TYPE_DEF:
7390 if (image->assembly)
7391 return mono_stringify_assembly_name (&image->assembly->aname);
7392 else if (image->assembly_name)
7393 return g_strdup (image->assembly_name);
7394 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7395 case MONO_TOKEN_TYPE_REF: {
7397 MonoAssemblyName aname;
7398 guint32 cols [MONO_TYPEREF_SIZE];
7399 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7400 guint32 idx = mono_metadata_token_index (type_token);
7403 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7405 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7406 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7407 mono_error_cleanup (&error);
7410 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7412 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7413 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7414 case MONO_RESOLUTION_SCOPE_MODULE:
7416 return g_strdup ("");
7417 case MONO_RESOLUTION_SCOPE_MODULEREF:
7419 return g_strdup ("");
7420 case MONO_RESOLUTION_SCOPE_TYPEREF:
7422 return g_strdup ("");
7423 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7424 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7425 return mono_stringify_assembly_name (&aname);
7427 g_assert_not_reached ();
7431 case MONO_TOKEN_TYPE_SPEC:
7433 return g_strdup ("");
7435 g_assert_not_reached ();
7442 * mono_class_get_full:
7443 * @image: the image where the class resides
7444 * @type_token: the token for the class
7445 * @context: the generic context used to evaluate generic instantiations in
7446 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7448 * Returns: The MonoClass that represents @type_token in @image
7451 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7455 klass = mono_class_get_checked (image, type_token, &error);
7457 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7458 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7460 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7466 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7470 mono_error_init (error);
7471 klass = mono_class_get_checked (image, type_token, error);
7473 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7474 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7479 * mono_class_get_checked:
7480 * @image: the image where the class resides
7481 * @type_token: the token for the class
7482 * @error: error object to return any error
7484 * Returns: The MonoClass that represents @type_token in @image, or NULL on error.
7487 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7489 MonoClass *klass = NULL;
7491 mono_error_init (error);
7493 if (image_is_dynamic (image)) {
7494 int table = mono_metadata_token_table (type_token);
7496 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7497 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7500 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
7504 switch (type_token & 0xff000000){
7505 case MONO_TOKEN_TYPE_DEF:
7506 klass = mono_class_create_from_typedef (image, type_token, error);
7508 case MONO_TOKEN_TYPE_REF:
7509 klass = mono_class_from_typeref_checked (image, type_token, error);
7511 case MONO_TOKEN_TYPE_SPEC:
7512 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7515 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7519 /* Generic case, should be avoided for when a better error is possible. */
7520 if (!klass && mono_error_ok (error)) {
7521 char *name = mono_class_name_from_token (image, type_token);
7522 char *assembly = mono_assembly_name_from_token (image, type_token);
7523 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7531 * mono_type_get_checked:
7532 * @image: the image where the type resides
7533 * @type_token: the token for the type
7534 * @context: the generic context used to evaluate generic instantiations in
7535 * @error: Error handling context
7537 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7539 * Returns: The MonoType that represents @type_token in @image
7542 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7544 MonoType *type = NULL;
7545 gboolean inflated = FALSE;
7547 mono_error_init (error);
7549 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7550 if (image_is_dynamic (image)) {
7551 MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
7552 return_val_if_nok (error, NULL);
7553 return mono_class_get_type (klass);
7556 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7557 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7564 return mono_class_get_type (klass);
7567 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7574 MonoType *tmp = type;
7575 type = mono_class_get_type (mono_class_from_mono_type (type));
7576 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7577 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7578 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7580 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7582 if (type->type != tmp->type)
7585 mono_metadata_free_type (tmp);
7592 * @image: image where the class token will be looked up.
7593 * @type_token: a type token from the image
7595 * Returns the MonoClass with the given @type_token on the @image
7598 mono_class_get (MonoImage *image, guint32 type_token)
7600 return mono_class_get_full (image, type_token, NULL);
7604 * mono_image_init_name_cache:
7606 * Initializes the class name cache stored in image->name_cache.
7608 * LOCKING: Acquires the corresponding image lock.
7611 mono_image_init_name_cache (MonoImage *image)
7613 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7614 guint32 cols [MONO_TYPEDEF_SIZE];
7617 guint32 i, visib, nspace_index;
7618 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7620 if (image->name_cache)
7623 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7625 if (image_is_dynamic (image)) {
7626 mono_image_lock (image);
7627 if (image->name_cache) {
7628 /* Somebody initialized it before us */
7629 g_hash_table_destroy (the_name_cache);
7631 mono_atomic_store_release (&image->name_cache, the_name_cache);
7633 mono_image_unlock (image);
7637 /* Temporary hash table to avoid lookups in the nspace_table */
7638 name_cache2 = g_hash_table_new (NULL, NULL);
7640 for (i = 1; i <= t->rows; ++i) {
7641 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7642 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7644 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7645 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7647 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7649 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7650 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7652 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7653 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7654 if (!nspace_table) {
7655 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7656 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7657 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7660 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7663 /* Load type names from EXPORTEDTYPES table */
7665 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7666 guint32 cols [MONO_EXP_TYPE_SIZE];
7669 for (i = 0; i < t->rows; ++i) {
7670 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7672 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7673 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7677 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7678 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7680 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7681 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7682 if (!nspace_table) {
7683 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7684 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7685 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7688 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7692 g_hash_table_destroy (name_cache2);
7694 mono_image_lock (image);
7695 if (image->name_cache) {
7696 /* Somebody initialized it before us */
7697 g_hash_table_destroy (the_name_cache);
7699 mono_atomic_store_release (&image->name_cache, the_name_cache);
7701 mono_image_unlock (image);
7704 /*FIXME Only dynamic assemblies should allow this operation.*/
7706 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7707 const char *name, guint32 index)
7709 GHashTable *nspace_table;
7710 GHashTable *name_cache;
7713 mono_image_init_name_cache (image);
7714 mono_image_lock (image);
7716 name_cache = image->name_cache;
7717 if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7718 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7719 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7722 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7723 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7725 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7727 mono_image_unlock (image);
7736 find_nocase (gpointer key, gpointer value, gpointer user_data)
7738 char *name = (char*)key;
7739 FindUserData *data = (FindUserData*)user_data;
7741 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7742 data->value = value;
7746 * mono_class_from_name_case:
7747 * @image: The MonoImage where the type is looked up in
7748 * @name_space: the type namespace
7749 * @name: the type short name.
7750 * @deprecated: use the mono_class_from_name_case_checked variant instead.
7752 * Obtains a MonoClass with a given namespace and a given name which
7753 * is located in the given MonoImage. The namespace and name
7754 * lookups are case insensitive.
7757 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7760 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7761 mono_error_cleanup (&error);
7767 * mono_class_from_name_case:
7768 * @image: The MonoImage where the type is looked up in
7769 * @name_space: the type namespace
7770 * @name: the type short name.
7773 * Obtains a MonoClass with a given namespace and a given name which
7774 * is located in the given MonoImage. The namespace and name
7775 * lookups are case insensitive.
7777 * Returns: The MonoClass if the given namespace and name were found, or NULL if it
7778 * was not found. The @error object will contain information about the problem
7782 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7784 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7785 guint32 cols [MONO_TYPEDEF_SIZE];
7790 mono_error_init (error);
7792 if (image_is_dynamic (image)) {
7794 FindUserData user_data;
7796 mono_image_init_name_cache (image);
7797 mono_image_lock (image);
7799 user_data.key = name_space;
7800 user_data.value = NULL;
7801 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7803 if (user_data.value) {
7804 GHashTable *nspace_table = (GHashTable*)user_data.value;
7806 user_data.key = name;
7807 user_data.value = NULL;
7809 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7811 if (user_data.value)
7812 token = GPOINTER_TO_UINT (user_data.value);
7815 mono_image_unlock (image);
7818 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7824 /* add a cache if needed */
7825 for (i = 1; i <= t->rows; ++i) {
7826 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7827 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7829 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7830 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7832 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7834 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7835 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7836 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7837 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7843 return_nested_in (MonoClass *klass, char *nested)
7846 char *s = strchr (nested, '/');
7847 gpointer iter = NULL;
7854 while ((found = mono_class_get_nested_types (klass, &iter))) {
7855 if (strcmp (found->name, nested) == 0) {
7857 return return_nested_in (found, s);
7865 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7867 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7868 MonoImage *file_image;
7872 mono_error_init (error);
7875 * The EXPORTEDTYPES table only contains public types, so have to search the
7877 * Note: image->modules contains the contents of the MODULEREF table, while
7878 * the real module list is in the FILE table.
7880 for (i = 0; i < file_table->rows; i++) {
7881 guint32 cols [MONO_FILE_SIZE];
7882 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7883 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7886 file_image = mono_image_load_file_for_image_checked (image, i + 1, error);
7888 klass = mono_class_from_name_checked (file_image, name_space, name, error);
7889 if (klass || !is_ok (error))
7898 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7900 GHashTable *nspace_table;
7901 MonoImage *loaded_image;
7908 mono_error_init (error);
7910 // Checking visited images avoids stack overflows when cyclic references exist.
7911 if (g_hash_table_lookup (visited_images, image))
7914 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7916 if ((nested = strchr (name, '/'))) {
7917 int pos = nested - name;
7918 int len = strlen (name);
7921 memcpy (buf, name, len + 1);
7923 nested = buf + pos + 1;
7927 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7928 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7929 gboolean res = get_class_from_name (image, name_space, name, &klass);
7932 klass = search_modules (image, name_space, name, error);
7937 return klass ? return_nested_in (klass, nested) : NULL;
7943 mono_image_init_name_cache (image);
7944 mono_image_lock (image);
7946 nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7949 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7951 mono_image_unlock (image);
7953 if (!token && image_is_dynamic (image) && image->modules) {
7954 /* Search modules as well */
7955 for (i = 0; i < image->module_count; ++i) {
7956 MonoImage *module = image->modules [i];
7958 klass = mono_class_from_name_checked (module, name_space, name, error);
7959 if (klass || !is_ok (error))
7965 klass = search_modules (image, name_space, name, error);
7966 if (klass || !is_ok (error))
7971 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7972 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7973 guint32 cols [MONO_EXP_TYPE_SIZE];
7976 idx = mono_metadata_token_index (token);
7978 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7980 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7981 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7982 loaded_image = mono_assembly_load_module_checked (image->assembly, impl >> MONO_IMPLEMENTATION_BITS, error);
7985 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7987 return klass ? return_nested_in (klass, nested) : NULL;
7989 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7990 guint32 assembly_idx;
7992 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7994 mono_assembly_load_reference (image, assembly_idx - 1);
7995 g_assert (image->references [assembly_idx - 1]);
7996 if (image->references [assembly_idx - 1] == (gpointer)-1)
7998 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
8000 return klass ? return_nested_in (klass, nested) : NULL;
8003 g_assert_not_reached ();
8007 token = MONO_TOKEN_TYPE_DEF | token;
8009 klass = mono_class_get_checked (image, token, error);
8011 return return_nested_in (klass, nested);
8016 * mono_class_from_name_checked:
8017 * @image: The MonoImage where the type is looked up in
8018 * @name_space: the type namespace
8019 * @name: the type short name.
8021 * Obtains a MonoClass with a given namespace and a given name which
8022 * is located in the given MonoImage.
8024 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
8025 * set if the class was not found or it will return NULL and set the error if there was a loading error.
8028 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
8031 GHashTable *visited_images;
8033 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
8035 klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
8037 g_hash_table_destroy (visited_images);
8043 * mono_class_from_name:
8044 * @image: The MonoImage where the type is looked up in
8045 * @name_space: the type namespace
8046 * @name: the type short name.
8048 * Obtains a MonoClass with a given namespace and a given name which
8049 * is located in the given MonoImage.
8051 * To reference nested classes, use the "/" character as a separator.
8052 * For example use "Foo/Bar" to reference the class Bar that is nested
8053 * inside Foo, like this: "class Foo { class Bar {} }".
8056 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
8061 klass = mono_class_from_name_checked (image, name_space, name, &error);
8062 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
8068 * mono_class_load_from_name:
8069 * @image: The MonoImage where the type is looked up in
8070 * @name_space: the type namespace
8071 * @name: the type short name.
8073 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
8074 * This function should be used by the runtime for critical types to which there's no way to recover but crash
8075 * If they are missing. Thing of System.Object or System.String.
8078 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
8083 klass = mono_class_from_name_checked (image, name_space, name, &error);
8085 g_error ("Runtime critical type %s.%s not found", name_space, name);
8086 if (!mono_error_ok (&error))
8087 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8092 * mono_class_try_load_from_name:
8093 * @image: The MonoImage where the type is looked up in
8094 * @name_space: the type namespace
8095 * @name: the type short name.
8097 * This function tries to load a type, returning the class was found or NULL otherwise.
8098 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
8100 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
8101 * a type that we would otherwise assume to be available but was not due some error.
8105 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
8110 klass = mono_class_from_name_checked (image, name_space, name, &error);
8111 if (!mono_error_ok (&error))
8112 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8118 * mono_class_is_subclass_of:
8119 * @klass: class to probe if it is a subclass of another one
8120 * @klassc: the class we suspect is the base class
8121 * @check_interfaces: whether we should perform interface checks
8123 * This method determines whether @klass is a subclass of @klassc.
8125 * If the @check_interfaces flag is set, then if @klassc is an interface
8126 * this method return TRUE if the @klass implements the interface or
8127 * if @klass is an interface, if one of its base classes is @klass.
8129 * If @check_interfaces is false then, then if @klass is not an interface
8130 * then it returns TRUE if the @klass is a subclass of @klassc.
8132 * if @klass is an interface and @klassc is System.Object, then this function
8137 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
8138 gboolean check_interfaces)
8140 /* FIXME test for interfaces with variant generic arguments */
8141 mono_class_init (klass);
8142 mono_class_init (klassc);
8144 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
8145 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
8147 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
8150 for (i = 0; i < klass->interface_count; i ++) {
8151 MonoClass *ic = klass->interfaces [i];
8156 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
8161 * MS.NET thinks interfaces are a subclass of Object, so we think it as
8164 if (klassc == mono_defaults.object_class)
8171 mono_type_is_generic_argument (MonoType *type)
8173 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
8177 mono_class_has_variant_generic_params (MonoClass *klass)
8180 MonoGenericContainer *container;
8182 if (!mono_class_is_ginst (klass))
8185 container = mono_class_get_generic_container (mono_class_get_generic_class (klass)->container_class);
8187 for (i = 0; i < container->type_argc; ++i)
8188 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8195 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8197 if (target == candidate)
8200 if (check_for_reference_conv &&
8201 mono_type_is_generic_argument (&target->byval_arg) &&
8202 mono_type_is_generic_argument (&candidate->byval_arg)) {
8203 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8204 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8206 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8209 if (!mono_class_is_assignable_from (target, candidate))
8215 * @container the generic container from the GTD
8216 * @klass: the class to be assigned to
8217 * @oklass: the source class
8219 * Both @klass and @oklass must be instances of the same generic interface.
8221 * Returns: TRUE if @klass can be assigned to a @klass variable
8224 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8227 MonoType **klass_argv, **oklass_argv;
8228 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8229 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8231 if (klass == oklass)
8234 /*Viable candidates are instances of the same generic interface*/
8235 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8238 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8239 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8241 for (j = 0; j < container->type_argc; ++j) {
8242 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8243 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8245 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8249 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8250 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8252 if (param1_class != param2_class) {
8253 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8254 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8256 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8257 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8267 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8269 MonoGenericParam *gparam, *ogparam;
8270 MonoGenericParamInfo *tinfo, *cinfo;
8271 MonoClass **candidate_class;
8272 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8275 if (target == candidate)
8277 if (target->byval_arg.type != candidate->byval_arg.type)
8280 gparam = target->byval_arg.data.generic_param;
8281 ogparam = candidate->byval_arg.data.generic_param;
8282 tinfo = mono_generic_param_info (gparam);
8283 cinfo = mono_generic_param_info (ogparam);
8285 class_constraint_satisfied = FALSE;
8286 valuetype_constraint_satisfied = FALSE;
8288 /*candidate must have a super set of target's special constraints*/
8289 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8290 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8292 if (cinfo->constraints) {
8293 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8294 MonoClass *cc = *candidate_class;
8296 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8297 class_constraint_satisfied = TRUE;
8298 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8299 valuetype_constraint_satisfied = TRUE;
8302 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8303 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8305 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8307 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8309 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8310 valuetype_constraint_satisfied)) {
8315 /*candidate type constraints must be a superset of target's*/
8316 if (tinfo->constraints) {
8317 MonoClass **target_class;
8318 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8319 MonoClass *tc = *target_class;
8322 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8323 * check it's constraints since it satisfy the constraint by itself.
8325 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8328 if (!cinfo->constraints)
8331 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8332 MonoClass *cc = *candidate_class;
8334 if (mono_class_is_assignable_from (tc, cc))
8338 * This happens when we have the following:
8340 * Bar<K> where K : IFace
8341 * Foo<T, U> where T : U where U : IFace
8343 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8346 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8347 if (mono_gparam_is_assignable_from (target, cc))
8351 if (!*candidate_class)
8356 /*candidate itself must have a constraint that satisfy target*/
8357 if (cinfo->constraints) {
8358 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8359 MonoClass *cc = *candidate_class;
8360 if (mono_class_is_assignable_from (target, cc))
8368 * mono_class_is_assignable_from:
8369 * @klass: the class to be assigned to
8370 * @oklass: the source class
8372 * Returns: TRUE if an instance of object oklass can be assigned to an
8373 * instance of object @klass
8376 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8379 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8381 mono_class_init (klass);
8383 if (!oklass->inited)
8384 mono_class_init (oklass);
8386 if (mono_class_has_failure (klass) || mono_class_has_failure (oklass))
8389 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8390 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8392 return mono_gparam_is_assignable_from (klass, oklass);
8395 if (MONO_CLASS_IS_INTERFACE (klass)) {
8396 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8397 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8398 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8402 for (i = 0; constraints [i]; ++i) {
8403 if (mono_class_is_assignable_from (klass, constraints [i]))
8411 /* interface_offsets might not be set for dynamic classes */
8412 if (mono_class_get_ref_info_handle (oklass) && !oklass->interface_bitmap) {
8414 * oklass might be a generic type parameter but they have
8415 * interface_offsets set.
8417 gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8418 if (!is_ok (&error)) {
8419 mono_error_cleanup (&error);
8424 if (!oklass->interface_bitmap)
8425 /* Happens with generic instances of not-yet created dynamic types */
8427 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8430 if (mono_class_has_variant_generic_params (klass)) {
8432 mono_class_setup_interfaces (oklass, &error);
8433 if (!mono_error_ok (&error)) {
8434 mono_error_cleanup (&error);
8438 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8439 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8440 MonoClass *iface = oklass->interfaces_packed [i];
8442 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8447 } else if (klass->delegate) {
8448 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8450 }else if (klass->rank) {
8451 MonoClass *eclass, *eoclass;
8453 if (oklass->rank != klass->rank)
8456 /* vectors vs. one dimensional arrays */
8457 if (oklass->byval_arg.type != klass->byval_arg.type)
8460 eclass = klass->cast_class;
8461 eoclass = oklass->cast_class;
8464 * a is b does not imply a[] is b[] when a is a valuetype, and
8465 * b is a reference type.
8468 if (eoclass->valuetype) {
8469 if ((eclass == mono_defaults.enum_class) ||
8470 (eclass == mono_defaults.enum_class->parent) ||
8471 (eclass == mono_defaults.object_class))
8475 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8476 } else if (mono_class_is_nullable (klass)) {
8477 if (mono_class_is_nullable (oklass))
8478 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8480 return mono_class_is_assignable_from (klass->cast_class, oklass);
8481 } else if (klass == mono_defaults.object_class)
8484 return mono_class_has_parent (oklass, klass);
8487 /*Check if @oklass is variant compatible with @klass.*/
8489 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8492 MonoType **klass_argv, **oklass_argv;
8493 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8494 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8496 /*Viable candidates are instances of the same generic interface*/
8497 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8500 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8501 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8503 for (j = 0; j < container->type_argc; ++j) {
8504 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8505 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8507 if (param1_class->valuetype != param2_class->valuetype)
8511 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8512 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8514 if (param1_class != param2_class) {
8515 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8516 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8518 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8519 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8527 /*Check if @candidate implements the interface @target*/
8529 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8533 gboolean is_variant = mono_class_has_variant_generic_params (target);
8535 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8536 if (mono_class_is_variant_compatible_slow (target, candidate))
8541 if (candidate == target)
8544 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8545 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8546 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (candidate);
8548 if (tb && tb->interfaces) {
8549 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8550 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8551 MonoClass *iface_class;
8553 /* we can't realize the type here since it can do pretty much anything. */
8556 iface_class = mono_class_from_mono_type (iface->type);
8557 if (iface_class == target)
8559 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8561 if (mono_class_implement_interface_slow (target, iface_class))
8566 /*setup_interfaces don't mono_class_init anything*/
8567 /*FIXME this doesn't handle primitive type arrays.
8568 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8569 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8571 mono_class_setup_interfaces (candidate, &error);
8572 if (!mono_error_ok (&error)) {
8573 mono_error_cleanup (&error);
8577 for (i = 0; i < candidate->interface_count; ++i) {
8578 if (candidate->interfaces [i] == target)
8581 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8584 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8588 candidate = candidate->parent;
8589 } while (candidate);
8595 * Check if @oklass can be assigned to @klass.
8596 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8599 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8601 if (candidate == target)
8603 if (target == mono_defaults.object_class)
8606 if (mono_class_has_parent (candidate, target))
8609 /*If target is not an interface there is no need to check them.*/
8610 if (MONO_CLASS_IS_INTERFACE (target))
8611 return mono_class_implement_interface_slow (target, candidate);
8613 if (target->delegate && mono_class_has_variant_generic_params (target))
8614 return mono_class_is_variant_compatible (target, candidate, FALSE);
8617 MonoClass *eclass, *eoclass;
8619 if (target->rank != candidate->rank)
8622 /* vectors vs. one dimensional arrays */
8623 if (target->byval_arg.type != candidate->byval_arg.type)
8626 eclass = target->cast_class;
8627 eoclass = candidate->cast_class;
8630 * a is b does not imply a[] is b[] when a is a valuetype, and
8631 * b is a reference type.
8634 if (eoclass->valuetype) {
8635 if ((eclass == mono_defaults.enum_class) ||
8636 (eclass == mono_defaults.enum_class->parent) ||
8637 (eclass == mono_defaults.object_class))
8641 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8643 /*FIXME properly handle nullables */
8644 /*FIXME properly handle (M)VAR */
8649 * mono_class_get_cctor:
8650 * @klass: A MonoClass pointer
8652 * Returns: The static constructor of @klass if it exists, NULL otherwise.
8655 mono_class_get_cctor (MonoClass *klass)
8657 MonoCachedClassInfo cached_info;
8659 if (image_is_dynamic (klass->image)) {
8661 * has_cctor is not set for these classes because mono_class_init () is
8664 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8667 if (!klass->has_cctor)
8670 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8672 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8673 if (!mono_error_ok (&error))
8674 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8678 if (mono_class_is_ginst (klass) && !klass->methods)
8679 return mono_class_get_inflated_method (klass, mono_class_get_cctor (mono_class_get_generic_class (klass)->container_class));
8681 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8685 * mono_class_get_finalizer:
8686 * @klass: The MonoClass pointer
8688 * Returns: The finalizer method of @klass if it exists, NULL otherwise.
8691 mono_class_get_finalizer (MonoClass *klass)
8693 MonoCachedClassInfo cached_info;
8696 mono_class_init (klass);
8697 if (!mono_class_has_finalizer (klass))
8700 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8702 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8703 if (!mono_error_ok (&error))
8704 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8707 mono_class_setup_vtable (klass);
8708 return klass->vtable [finalize_slot];
8713 * mono_class_needs_cctor_run:
8714 * @klass: the MonoClass pointer
8715 * @caller: a MonoMethod describing the caller
8717 * Determines whenever the class has a static constructor and whenever it
8718 * needs to be called when executing CALLER.
8721 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8725 method = mono_class_get_cctor (klass);
8727 return (method == caller) ? FALSE : TRUE;
8733 * mono_class_array_element_size:
8736 * Returns: The number of bytes an element of type @klass
8737 * uses when stored into an array.
8740 mono_class_array_element_size (MonoClass *klass)
8742 MonoType *type = &klass->byval_arg;
8745 switch (type->type) {
8748 case MONO_TYPE_BOOLEAN:
8752 case MONO_TYPE_CHAR:
8761 case MONO_TYPE_CLASS:
8762 case MONO_TYPE_STRING:
8763 case MONO_TYPE_OBJECT:
8764 case MONO_TYPE_SZARRAY:
8765 case MONO_TYPE_ARRAY:
8766 return sizeof (gpointer);
8771 case MONO_TYPE_VALUETYPE:
8772 if (type->data.klass->enumtype) {
8773 type = mono_class_enum_basetype (type->data.klass);
8774 klass = klass->element_class;
8777 return mono_class_instance_size (klass) - sizeof (MonoObject);
8778 case MONO_TYPE_GENERICINST:
8779 type = &type->data.generic_class->container_class->byval_arg;
8782 case MONO_TYPE_MVAR: {
8785 return mono_type_size (type, &align);
8787 case MONO_TYPE_VOID:
8791 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8797 * mono_array_element_size:
8798 * @ac: pointer to a #MonoArrayClass
8800 * Returns: The size of single array element.
8803 mono_array_element_size (MonoClass *ac)
8805 g_assert (ac->rank);
8806 return ac->sizes.element_size;
8810 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8811 MonoGenericContext *context)
8814 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8815 g_assert (mono_error_ok (&error));
8820 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8821 MonoGenericContext *context, MonoError *error)
8823 mono_error_init (error);
8825 if (image_is_dynamic (image)) {
8826 MonoClass *tmp_handle_class;
8827 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
8829 mono_error_assert_ok (error);
8830 g_assert (tmp_handle_class);
8832 *handle_class = tmp_handle_class;
8834 if (tmp_handle_class == mono_defaults.typehandle_class)
8835 return &((MonoClass*)obj)->byval_arg;
8840 switch (token & 0xff000000) {
8841 case MONO_TOKEN_TYPE_DEF:
8842 case MONO_TOKEN_TYPE_REF:
8843 case MONO_TOKEN_TYPE_SPEC: {
8846 *handle_class = mono_defaults.typehandle_class;
8847 type = mono_type_get_checked (image, token, context, error);
8851 mono_class_init (mono_class_from_mono_type (type));
8852 /* We return a MonoType* as handle */
8855 case MONO_TOKEN_FIELD_DEF: {
8857 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8859 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8863 *handle_class = mono_defaults.fieldhandle_class;
8864 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8868 mono_class_init (klass);
8869 return mono_class_get_field (klass, token);
8871 case MONO_TOKEN_METHOD_DEF:
8872 case MONO_TOKEN_METHOD_SPEC: {
8874 meth = mono_get_method_checked (image, token, NULL, context, error);
8876 *handle_class = mono_defaults.methodhandle_class;
8882 case MONO_TOKEN_MEMBER_REF: {
8883 guint32 cols [MONO_MEMBERREF_SIZE];
8885 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8886 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8887 mono_metadata_decode_blob_size (sig, &sig);
8888 if (*sig == 0x6) { /* it's a field */
8890 MonoClassField *field;
8891 field = mono_field_from_token_checked (image, token, &klass, context, error);
8893 *handle_class = mono_defaults.fieldhandle_class;
8897 meth = mono_get_method_checked (image, token, NULL, context, error);
8899 *handle_class = mono_defaults.methodhandle_class;
8904 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8910 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
8912 MonoClass *handle_class;
8913 mono_error_init (error);
8914 return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
8918 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
8920 return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
8923 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8926 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8928 get_cached_class_info = func;
8932 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8934 if (!get_cached_class_info)
8937 return get_cached_class_info (klass, res);
8941 mono_install_get_class_from_name (MonoGetClassFromName func)
8943 get_class_from_name = func;
8947 * mono_class_get_image:
8949 * Use this method to get the `MonoImage*` where this class came from.
8951 * Returns: The image where this class is defined.
8954 mono_class_get_image (MonoClass *klass)
8956 return klass->image;
8960 * mono_class_get_element_class:
8961 * @klass: the MonoClass to act on
8963 * Use this function to get the element class of an array.
8965 * Returns: The element class of an array.
8968 mono_class_get_element_class (MonoClass *klass)
8970 return klass->element_class;
8974 * mono_class_is_valuetype:
8975 * @klass: the MonoClass to act on
8977 * Use this method to determine if the provided `MonoClass*` represents a value type,
8978 * or a reference type.
8980 * Returns: TRUE if the MonoClass represents a ValueType, FALSE if it represents a reference type.
8983 mono_class_is_valuetype (MonoClass *klass)
8985 return klass->valuetype;
8989 * mono_class_is_enum:
8990 * @klass: the MonoClass to act on
8992 * Use this function to determine if the provided `MonoClass*` represents an enumeration.
8994 * Returns: TRUE if the MonoClass represents an enumeration.
8997 mono_class_is_enum (MonoClass *klass)
8999 return klass->enumtype;
9003 * mono_class_enum_basetype:
9004 * @klass: the MonoClass to act on
9006 * Use this function to get the underlying type for an enumeration value.
9008 * Returns: The underlying type representation for an enumeration.
9011 mono_class_enum_basetype (MonoClass *klass)
9013 if (klass->element_class == klass)
9014 /* SRE or broken types */
9017 return &klass->element_class->byval_arg;
9021 * mono_class_get_parent
9022 * @klass: the MonoClass to act on
9024 * Returns: The parent class for this class.
9027 mono_class_get_parent (MonoClass *klass)
9029 return klass->parent;
9033 * mono_class_get_nesting_type:
9034 * @klass: the MonoClass to act on
9036 * Use this function to obtain the class that the provided `MonoClass*` is nested on.
9038 * If the return is NULL, this indicates that this class is not nested.
9040 * Returns: The container type where this type is nested or NULL if this type is not a nested type.
9043 mono_class_get_nesting_type (MonoClass *klass)
9045 return klass->nested_in;
9049 * mono_class_get_rank:
9050 * @klass: the MonoClass to act on
9052 * Returns: The rank for the array (the number of dimensions).
9055 mono_class_get_rank (MonoClass *klass)
9061 * mono_class_get_name
9062 * @klass: the MonoClass to act on
9064 * Returns: The name of the class.
9067 mono_class_get_name (MonoClass *klass)
9073 * mono_class_get_namespace:
9074 * @klass: the MonoClass to act on
9076 * Returns: The namespace of the class.
9079 mono_class_get_namespace (MonoClass *klass)
9081 return klass->name_space;
9085 * mono_class_get_type:
9086 * @klass: the MonoClass to act on
9088 * This method returns the internal Type representation for the class.
9090 * Returns: The MonoType from the class.
9093 mono_class_get_type (MonoClass *klass)
9095 return &klass->byval_arg;
9099 * mono_class_get_type_token:
9100 * @klass: the MonoClass to act on
9102 * This method returns type token for the class.
9104 * Returns: The type token for the class.
9107 mono_class_get_type_token (MonoClass *klass)
9109 return klass->type_token;
9113 * mono_class_get_byref_type:
9114 * @klass: the MonoClass to act on
9119 mono_class_get_byref_type (MonoClass *klass)
9121 return &klass->this_arg;
9125 * mono_class_num_fields:
9126 * @klass: the MonoClass to act on
9128 * Returns: The number of static and instance fields in the class.
9131 mono_class_num_fields (MonoClass *klass)
9133 return mono_class_get_field_count (klass);
9137 * mono_class_num_methods:
9138 * @klass: the MonoClass to act on
9140 * Returns: The number of methods in the class.
9143 mono_class_num_methods (MonoClass *klass)
9145 return mono_class_get_method_count (klass);
9149 * mono_class_num_properties
9150 * @klass: the MonoClass to act on
9152 * Returns: The number of properties in the class.
9155 mono_class_num_properties (MonoClass *klass)
9157 mono_class_setup_properties (klass);
9159 return mono_class_get_ext (klass)->property.count;
9163 * mono_class_num_events:
9164 * @klass: the MonoClass to act on
9166 * Returns: The number of events in the class.
9169 mono_class_num_events (MonoClass *klass)
9171 mono_class_setup_events (klass);
9173 return mono_class_get_ext (klass)->event.count;
9177 * mono_class_get_fields:
9178 * @klass: the MonoClass to act on
9180 * This routine is an iterator routine for retrieving the fields in a class.
9182 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9183 * iterate over all of the elements. When no more values are
9184 * available, the return value is NULL.
9186 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
9189 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9191 MonoClassField* field;
9195 mono_class_setup_fields (klass);
9196 if (mono_class_has_failure (klass))
9198 /* start from the first */
9199 if (mono_class_get_field_count (klass)) {
9200 *iter = &klass->fields [0];
9201 return &klass->fields [0];
9207 field = (MonoClassField *)*iter;
9209 if (field < &klass->fields [mono_class_get_field_count (klass)]) {
9217 * mono_class_get_methods
9218 * @klass: the MonoClass to act on
9220 * This routine is an iterator routine for retrieving the fields in a class.
9222 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9223 * iterate over all of the elements. When no more values are
9224 * available, the return value is NULL.
9226 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
9229 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9231 MonoMethod** method;
9235 mono_class_setup_methods (klass);
9238 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9239 * FIXME we should better report this error to the caller
9241 if (!klass->methods)
9243 /* start from the first */
9244 if (mono_class_get_method_count (klass)) {
9245 *iter = &klass->methods [0];
9246 return klass->methods [0];
9252 method = (MonoMethod **)*iter;
9254 if (method < &klass->methods [mono_class_get_method_count (klass)]) {
9262 * mono_class_get_virtual_methods:
9264 * Iterate over the virtual methods of KLASS.
9266 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9269 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9271 MonoMethod** method;
9274 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9276 mono_class_setup_methods (klass);
9278 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9279 * FIXME we should better report this error to the caller
9281 if (!klass->methods)
9283 /* start from the first */
9284 method = &klass->methods [0];
9286 method = (MonoMethod **)*iter;
9289 int mcount = mono_class_get_method_count (klass);
9290 while (method < &klass->methods [mcount]) {
9291 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9295 if (method < &klass->methods [mcount]) {
9302 /* Search directly in metadata to avoid calling setup_methods () */
9303 MonoMethod *res = NULL;
9309 start_index = GPOINTER_TO_UINT (*iter);
9312 int first_idx = mono_class_get_first_method_idx (klass);
9313 int mcount = mono_class_get_method_count (klass);
9314 for (i = start_index; i < mcount; ++i) {
9317 /* first_idx points into the methodptr table */
9318 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
9320 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9326 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9327 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9329 /* Add 1 here so the if (*iter) check fails */
9330 *iter = GUINT_TO_POINTER (i + 1);
9339 * mono_class_get_properties:
9340 * @klass: the MonoClass to act on
9342 * This routine is an iterator routine for retrieving the properties in a class.
9344 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9345 * iterate over all of the elements. When no more values are
9346 * available, the return value is NULL.
9348 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9351 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9353 MonoProperty* property;
9357 mono_class_setup_properties (klass);
9358 MonoClassExt *ext = mono_class_get_ext (klass);
9359 /* start from the first */
9360 if (ext->property.count) {
9361 *iter = &ext->properties [0];
9362 return (MonoProperty *)*iter;
9368 property = (MonoProperty *)*iter;
9370 MonoClassExt *ext = mono_class_get_ext (klass);
9371 if (property < &ext->properties [ext->property.count]) {
9373 return (MonoProperty *)*iter;
9379 * mono_class_get_events:
9380 * @klass: the MonoClass to act on
9382 * This routine is an iterator routine for retrieving the properties in a class.
9384 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9385 * iterate over all of the elements. When no more values are
9386 * available, the return value is NULL.
9388 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9391 mono_class_get_events (MonoClass* klass, gpointer *iter)
9397 mono_class_setup_events (klass);
9398 MonoClassExt *ext = mono_class_get_ext (klass);
9399 /* start from the first */
9400 if (ext->event.count) {
9401 *iter = &ext->events [0];
9402 return (MonoEvent *)*iter;
9408 event = (MonoEvent *)*iter;
9410 MonoClassExt *ext = mono_class_get_ext (klass);
9411 if (event < &ext->events [ext->event.count]) {
9413 return (MonoEvent *)*iter;
9419 * mono_class_get_interfaces
9420 * @klass: the MonoClass to act on
9422 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9424 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9425 * iterate over all of the elements. When no more values are
9426 * available, the return value is NULL.
9428 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9431 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9439 mono_class_init (klass);
9440 if (!klass->interfaces_inited) {
9441 mono_class_setup_interfaces (klass, &error);
9442 if (!mono_error_ok (&error)) {
9443 mono_error_cleanup (&error);
9447 /* start from the first */
9448 if (klass->interface_count) {
9449 *iter = &klass->interfaces [0];
9450 return klass->interfaces [0];
9456 iface = (MonoClass **)*iter;
9458 if (iface < &klass->interfaces [klass->interface_count]) {
9466 setup_nested_types (MonoClass *klass)
9469 GList *classes, *nested_classes, *l;
9472 if (klass->nested_classes_inited)
9475 if (!klass->type_token)
9476 klass->nested_classes_inited = TRUE;
9478 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9482 guint32 cols [MONO_NESTED_CLASS_SIZE];
9483 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9484 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9485 if (!mono_error_ok (&error)) {
9486 /*FIXME don't swallow the error message*/
9487 mono_error_cleanup (&error);
9489 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9493 classes = g_list_prepend (classes, nclass);
9495 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9498 mono_class_alloc_ext (klass);
9500 nested_classes = NULL;
9501 for (l = classes; l; l = l->next)
9502 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9503 g_list_free (classes);
9505 mono_image_lock (klass->image);
9507 mono_memory_barrier ();
9508 if (!klass->nested_classes_inited) {
9509 mono_class_get_ext (klass)->nested_classes = nested_classes;
9510 mono_memory_barrier ();
9511 klass->nested_classes_inited = TRUE;
9514 mono_image_unlock (klass->image);
9518 * mono_class_get_nested_types
9519 * @klass: the MonoClass to act on
9521 * This routine is an iterator routine for retrieving the nested types of a class.
9522 * This works only if @klass is non-generic, or a generic type definition.
9524 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9525 * iterate over all of the elements. When no more values are
9526 * available, the return value is NULL.
9528 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9531 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9537 if (!klass->nested_classes_inited)
9538 setup_nested_types (klass);
9541 MonoClassExt *ext = mono_class_get_ext (klass);
9542 /* start from the first */
9543 if (ext && ext->nested_classes) {
9544 *iter = ext->nested_classes;
9545 return (MonoClass *)ext->nested_classes->data;
9547 /* no nested types */
9551 item = (GList *)*iter;
9555 return (MonoClass *)item->data;
9562 * mono_class_is_delegate
9563 * @klass: the MonoClass to act on
9565 * Returns: TRUE if the MonoClass represents a System.Delegate.
9568 mono_class_is_delegate (MonoClass *klass)
9570 return klass->delegate;
9574 * mono_class_implements_interface
9575 * @klass: The MonoClass to act on
9576 * @interface: The interface to check if @klass implements.
9578 * Returns: TRUE if @klass implements @interface.
9581 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9583 return mono_class_is_assignable_from (iface, klass);
9587 * mono_field_get_name:
9588 * @field: the MonoClassField to act on
9590 * Returns: The name of the field.
9593 mono_field_get_name (MonoClassField *field)
9599 * mono_field_get_type:
9600 * @field: the MonoClassField to act on
9602 * Returns: MonoType of the field.
9605 mono_field_get_type (MonoClassField *field)
9608 MonoType *type = mono_field_get_type_checked (field, &error);
9609 if (!mono_error_ok (&error)) {
9610 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9611 mono_error_cleanup (&error);
9618 * mono_field_get_type_checked:
9619 * @field: the MonoClassField to act on
9620 * @error: used to return any erro found while retrieving @field type
9622 * Returns: MonoType of the field.
9625 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9627 mono_error_init (error);
9629 mono_field_resolve_type (field, error);
9634 * mono_field_get_parent:
9635 * @field: the MonoClassField to act on
9637 * Returns: MonoClass where the field was defined.
9640 mono_field_get_parent (MonoClassField *field)
9642 return field->parent;
9646 * mono_field_get_flags;
9647 * @field: the MonoClassField to act on
9649 * The metadata flags for a field are encoded using the
9650 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9652 * Returns: The flags for the field.
9655 mono_field_get_flags (MonoClassField *field)
9658 return mono_field_resolve_flags (field);
9659 return field->type->attrs;
9663 * mono_field_get_offset:
9664 * @field: the MonoClassField to act on
9666 * Returns: The field offset.
9669 mono_field_get_offset (MonoClassField *field)
9671 return field->offset;
9675 mono_field_get_rva (MonoClassField *field)
9679 MonoClass *klass = field->parent;
9680 MonoFieldDefaultValue *field_def_values;
9682 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9684 MonoClassExt *ext = mono_class_get_ext (klass);
9685 if (!ext || !ext->field_def_values) {
9686 mono_class_alloc_ext (klass);
9687 ext = mono_class_get_ext (klass);
9689 field_def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
9691 mono_image_lock (klass->image);
9692 if (!ext->field_def_values)
9693 ext->field_def_values = field_def_values;
9694 mono_image_unlock (klass->image);
9697 field_index = mono_field_get_index (field);
9699 if (!ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9700 int first_field_idx = mono_class_get_first_field_idx (klass);
9701 mono_metadata_field_info (field->parent->image, first_field_idx + field_index, NULL, &rva, NULL);
9703 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9704 ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9707 return ext->field_def_values [field_index].data;
9711 * mono_field_get_data:
9712 * @field: the MonoClassField to act on
9714 * Returns: A pointer to the metadata constant value or to the field
9715 * data if it has an RVA flag.
9718 mono_field_get_data (MonoClassField *field)
9720 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9721 MonoTypeEnum def_type;
9723 return mono_class_get_field_default_value (field, &def_type);
9724 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9725 return mono_field_get_rva (field);
9732 * mono_property_get_name:
9733 * @prop: the MonoProperty to act on
9735 * Returns: The name of the property
9738 mono_property_get_name (MonoProperty *prop)
9744 * mono_property_get_set_method
9745 * @prop: the MonoProperty to act on.
9747 * Returns: The setter method of the property (A MonoMethod)
9750 mono_property_get_set_method (MonoProperty *prop)
9756 * mono_property_get_get_method
9757 * @prop: the MonoProperty to act on.
9759 * Returns: The setter method of the property (A MonoMethod)
9762 mono_property_get_get_method (MonoProperty *prop)
9768 * mono_property_get_parent:
9769 * @prop: the MonoProperty to act on.
9771 * Returns: The MonoClass where the property was defined.
9774 mono_property_get_parent (MonoProperty *prop)
9776 return prop->parent;
9780 * mono_property_get_flags:
9781 * @prop: the MonoProperty to act on.
9783 * The metadata flags for a property are encoded using the
9784 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9786 * Returns: The flags for the property.
9789 mono_property_get_flags (MonoProperty *prop)
9795 * mono_event_get_name:
9796 * @event: the MonoEvent to act on
9798 * Returns: The name of the event.
9801 mono_event_get_name (MonoEvent *event)
9807 * mono_event_get_add_method:
9808 * @event: The MonoEvent to act on.
9810 * Returns: The @add' method for the event (a MonoMethod).
9813 mono_event_get_add_method (MonoEvent *event)
9819 * mono_event_get_remove_method:
9820 * @event: The MonoEvent to act on.
9822 * Returns: The @remove method for the event (a MonoMethod).
9825 mono_event_get_remove_method (MonoEvent *event)
9827 return event->remove;
9831 * mono_event_get_raise_method:
9832 * @event: The MonoEvent to act on.
9834 * Returns: The @raise method for the event (a MonoMethod).
9837 mono_event_get_raise_method (MonoEvent *event)
9839 return event->raise;
9843 * mono_event_get_parent:
9844 * @event: the MonoEvent to act on.
9846 * Returns: The MonoClass where the event is defined.
9849 mono_event_get_parent (MonoEvent *event)
9851 return event->parent;
9855 * mono_event_get_flags
9856 * @event: the MonoEvent to act on.
9858 * The metadata flags for an event are encoded using the
9859 * EVENT_* constants. See the tabledefs.h file for details.
9861 * Returns: The flags for the event.
9864 mono_event_get_flags (MonoEvent *event)
9866 return event->attrs;
9870 * mono_class_get_method_from_name:
9871 * @klass: where to look for the method
9872 * @name: name of the method
9873 * @param_count: number of parameters. -1 for any number.
9875 * Obtains a MonoMethod with a given name and number of parameters.
9876 * It only works if there are no multiple signatures for any given method name.
9879 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9881 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9885 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9887 MonoMethod *res = NULL;
9890 /* Search directly in the metadata to avoid calling setup_methods () */
9891 int first_idx = mono_class_get_first_method_idx (klass);
9892 int mcount = mono_class_get_method_count (klass);
9893 for (i = 0; i < mcount; ++i) {
9895 guint32 cols [MONO_METHOD_SIZE];
9897 MonoMethodSignature *sig;
9899 /* first_idx points into the methodptr table */
9900 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, first_idx + i, cols, MONO_METHOD_SIZE);
9902 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9903 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9905 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9908 if (param_count == -1) {
9912 sig = mono_method_signature_checked (method, &error);
9914 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9917 if (sig->param_count == param_count) {
9928 * mono_class_get_method_from_name_flags:
9929 * @klass: where to look for the method
9930 * @name_space: name of the method
9931 * @param_count: number of parameters. -1 for any number.
9932 * @flags: flags which must be set in the method
9934 * Obtains a MonoMethod with a given name and number of parameters.
9935 * It only works if there are no multiple signatures for any given method name.
9938 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9940 MonoMethod *res = NULL;
9943 mono_class_init (klass);
9945 if (mono_class_is_ginst (klass) && !klass->methods) {
9946 res = mono_class_get_method_from_name_flags (mono_class_get_generic_class (klass)->container_class, name, param_count, flags);
9949 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9950 if (!mono_error_ok (&error))
9951 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9956 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9957 mono_class_setup_methods (klass);
9959 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9960 See mono/tests/array_load_exception.il
9961 FIXME we should better report this error to the caller
9963 if (!klass->methods)
9965 int mcount = mono_class_get_method_count (klass);
9966 for (i = 0; i < mcount; ++i) {
9967 MonoMethod *method = klass->methods [i];
9969 if (method->name[0] == name [0] &&
9970 !strcmp (name, method->name) &&
9971 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9972 ((method->flags & flags) == flags)) {
9979 res = find_method_in_metadata (klass, name, param_count, flags);
9986 * mono_class_set_failure:
9987 * @klass: class in which the failure was detected
9988 * @ex_type: the kind of exception/error to be thrown (later)
9989 * @ex_data: exception data (specific to each type of exception/error)
9991 * Keep a detected failure informations in the class for later processing.
9992 * Note that only the first failure is kept.
9994 * LOCKING: Acquires the loader lock.
9997 mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error)
9999 g_assert (boxed_error != NULL);
10001 if (mono_class_has_failure (klass))
10004 mono_loader_lock ();
10005 klass->has_failure = 1;
10006 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, boxed_error);
10007 mono_loader_unlock ();
10013 mono_class_has_failure (const MonoClass *klass)
10015 g_assert (klass != NULL);
10016 return klass->has_failure != 0;
10021 * mono_class_set_type_load_failure:
10022 * @klass: class in which the failure was detected
10023 * @fmt: Printf-style error message string.
10025 * Collect detected failure informaion in the class for later processing.
10026 * The error is stored as a MonoErrorBoxed as with mono_error_set_type_load_class ()
10027 * Note that only the first failure is kept.
10029 * Returns FALSE if a failure was already set on the class, or TRUE otherwise.
10031 * LOCKING: Acquires the loader lock.
10034 mono_class_set_type_load_failure (MonoClass *klass, const char * fmt, ...)
10036 MonoError prepare_error;
10039 if (mono_class_has_failure (klass))
10042 mono_error_init (&prepare_error);
10044 va_start (args, fmt);
10045 mono_error_vset_type_load_class (&prepare_error, klass, fmt, args);
10048 MonoErrorBoxed *box = mono_error_box (&prepare_error, klass->image);
10049 mono_error_cleanup (&prepare_error);
10050 return mono_class_set_failure (klass, box);
10054 * mono_class_get_exception_data:
10056 * Return the exception_data property of KLASS.
10058 * LOCKING: Acquires the loader lock.
10061 mono_class_get_exception_data (const MonoClass *klass)
10063 return mono_image_property_lookup (klass->image, (MonoClass*)klass, MONO_CLASS_PROP_EXCEPTION_DATA);
10067 * mono_classes_init:
10069 * Initialize the resources used by this module.
10072 mono_classes_init (void)
10074 mono_os_mutex_init (&classes_mutex);
10076 mono_native_tls_alloc (&setup_fields_tls_id, NULL);
10077 mono_native_tls_alloc (&init_pending_tls_id, NULL);
10079 mono_counters_register ("MonoClassDef count",
10080 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_def_count);
10081 mono_counters_register ("MonoClassGtd count",
10082 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gtd_count);
10083 mono_counters_register ("MonoClassGenericInst count",
10084 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ginst_count);
10085 mono_counters_register ("MonoClassGenericParam count",
10086 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gparam_count);
10087 mono_counters_register ("MonoClassArray count",
10088 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_array_count);
10089 mono_counters_register ("MonoClassPointer count",
10090 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_pointer_count);
10091 mono_counters_register ("Inflated methods size",
10092 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
10093 mono_counters_register ("Inflated classes size",
10094 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
10095 mono_counters_register ("MonoClass size",
10096 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
10097 mono_counters_register ("MonoClassExt size",
10098 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
10100 mono_counters_register ("MonoClassExt count",
10101 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_count);
10105 * mono_classes_cleanup:
10107 * Free the resources used by this module.
10110 mono_classes_cleanup (void)
10112 mono_native_tls_free (setup_fields_tls_id);
10113 mono_native_tls_free (init_pending_tls_id);
10115 if (global_interface_bitset)
10116 mono_bitset_free (global_interface_bitset);
10117 global_interface_bitset = NULL;
10118 mono_os_mutex_destroy (&classes_mutex);
10122 * mono_class_get_exception_for_failure:
10123 * @klass: class in which the failure was detected
10125 * Return a constructed MonoException than the caller can then throw
10126 * using mono_raise_exception - or NULL if no failure is present (or
10127 * doesn't result in an exception).
10130 mono_class_get_exception_for_failure (MonoClass *klass)
10132 if (!mono_class_has_failure (klass))
10134 MonoError unboxed_error;
10135 mono_error_init (&unboxed_error);
10136 mono_error_set_for_class_failure (&unboxed_error, klass);
10137 return mono_error_convert_to_exception (&unboxed_error);
10141 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
10143 outer_klass = mono_class_get_generic_type_definition (outer_klass);
10144 inner_klass = mono_class_get_generic_type_definition (inner_klass);
10146 if (outer_klass == inner_klass)
10148 inner_klass = inner_klass->nested_in;
10149 } while (inner_klass);
10154 mono_class_get_generic_type_definition (MonoClass *klass)
10156 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
10157 return gklass ? gklass->container_class : klass;
10161 * Check if @klass is a subtype of @parent ignoring generic instantiations.
10163 * Generic instantiations are ignored for all super types of @klass.
10165 * Visibility checks ignoring generic instantiations.
10168 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
10171 klass = mono_class_get_generic_type_definition (klass);
10172 parent = mono_class_get_generic_type_definition (parent);
10173 mono_class_setup_supertypes (klass);
10175 for (i = 0; i < klass->idepth; ++i) {
10176 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
10182 * Subtype can only access parent members with family protection if the site object
10183 * is subclass of Subtype. For example:
10184 * class A { protected int x; }
10186 * void valid_access () {
10190 * void invalid_access () {
10197 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
10199 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
10202 if (context_klass == NULL)
10204 /*if access_klass is not member_klass context_klass must be type compat*/
10205 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10211 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10214 if (accessing == accessed)
10216 if (!accessed || !accessing)
10219 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10220 * anywhere so untrusted friends are not safe to access platform's code internals */
10221 if (mono_security_core_clr_enabled ()) {
10222 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10226 mono_assembly_load_friends (accessed);
10227 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10228 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10229 /* Be conservative with checks */
10230 if (!friend_->name)
10232 if (strcmp (accessing->aname.name, friend_->name))
10234 if (friend_->public_key_token [0]) {
10235 if (!accessing->aname.public_key_token [0])
10237 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10246 * If klass is a generic type or if it is derived from a generic type, return the
10247 * MonoClass of the generic definition
10248 * Returns NULL if not found
10251 get_generic_definition_class (MonoClass *klass)
10254 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
10255 if (gklass && gklass->container_class)
10256 return gklass->container_class;
10257 klass = klass->parent;
10263 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10266 for (i = 0; i < ginst->type_argc; ++i) {
10267 MonoType *type = ginst->type_argv[i];
10268 switch (type->type) {
10269 case MONO_TYPE_SZARRAY:
10270 if (!can_access_type (access_klass, type->data.klass))
10273 case MONO_TYPE_ARRAY:
10274 if (!can_access_type (access_klass, type->data.array->eklass))
10277 case MONO_TYPE_PTR:
10278 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10281 case MONO_TYPE_CLASS:
10282 case MONO_TYPE_VALUETYPE:
10283 case MONO_TYPE_GENERICINST:
10284 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10294 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10298 if (access_klass == member_klass)
10301 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10304 if (access_klass->element_class && !access_klass->enumtype)
10305 access_klass = access_klass->element_class;
10307 if (member_klass->element_class && !member_klass->enumtype)
10308 member_klass = member_klass->element_class;
10310 access_level = mono_class_get_flags (member_klass) & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10312 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10315 if (mono_class_is_ginst (member_klass) && !can_access_instantiation (access_klass, mono_class_get_generic_class (member_klass)->context.class_inst))
10318 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10321 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10324 /*Non nested type with nested visibility. We just fail it.*/
10325 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10328 switch (access_level) {
10329 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10330 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10332 case TYPE_ATTRIBUTE_PUBLIC:
10335 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10338 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10339 return is_nesting_type (member_klass, access_klass);
10341 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10342 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10344 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10345 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10347 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10348 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10349 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10351 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10352 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10353 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10358 /* FIXME: check visibility of type, too */
10360 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10362 MonoClass *member_generic_def;
10363 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10366 MonoGenericClass *access_gklass = mono_class_try_get_generic_class (access_klass);
10367 if (((access_gklass && access_gklass->container_class) ||
10368 mono_class_is_gtd (access_klass)) &&
10369 (member_generic_def = get_generic_definition_class (member_klass))) {
10370 MonoClass *access_container;
10372 if (mono_class_is_gtd (access_klass))
10373 access_container = access_klass;
10375 access_container = access_gklass->container_class;
10377 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10381 /* Partition I 8.5.3.2 */
10382 /* the access level values are the same for fields and methods */
10383 switch (access_level) {
10384 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10385 /* same compilation unit */
10386 return access_klass->image == member_klass->image;
10387 case FIELD_ATTRIBUTE_PRIVATE:
10388 return access_klass == member_klass;
10389 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10390 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10391 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10394 case FIELD_ATTRIBUTE_ASSEMBLY:
10395 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10396 case FIELD_ATTRIBUTE_FAMILY:
10397 if (is_valid_family_access (access_klass, member_klass, context_klass))
10400 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10401 if (is_valid_family_access (access_klass, member_klass, context_klass))
10403 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10404 case FIELD_ATTRIBUTE_PUBLIC:
10411 * mono_method_can_access_field:
10412 * @method: Method that will attempt to access the field
10413 * @field: the field to access
10415 * Used to determine if a method is allowed to access the specified field.
10417 * Returns: TRUE if the given @method is allowed to access the @field while following
10418 * the accessibility rules of the CLI.
10421 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10423 /* FIXME: check all overlapping fields */
10424 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10426 MonoClass *nested = method->klass->nested_in;
10428 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10431 nested = nested->nested_in;
10438 * mono_method_can_access_method:
10439 * @method: Method that will attempt to access the other method
10440 * @called: the method that we want to probe for accessibility.
10442 * Used to determine if the @method is allowed to access the specified @called method.
10444 * Returns: TRUE if the given @method is allowed to invoke the @called while following
10445 * the accessibility rules of the CLI.
10448 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10450 method = mono_method_get_method_definition (method);
10451 called = mono_method_get_method_definition (called);
10452 return mono_method_can_access_method_full (method, called, NULL);
10456 * mono_method_can_access_method_full:
10457 * @method: The caller method
10458 * @called: The called method
10459 * @context_klass: The static type on stack of the owner @called object used
10461 * This function must be used with instance calls, as they have more strict family accessibility.
10462 * It can be used with static methods, but context_klass should be NULL.
10464 * Returns: TRUE if caller have proper visibility and acessibility to @called
10467 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10469 /* Wrappers are except from access checks */
10470 if (method->wrapper_type != MONO_WRAPPER_NONE || called->wrapper_type != MONO_WRAPPER_NONE)
10473 MonoClass *access_class = method->klass;
10474 MonoClass *member_class = called->klass;
10475 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10477 MonoClass *nested = access_class->nested_in;
10479 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10482 nested = nested->nested_in;
10489 can = can_access_type (access_class, member_class);
10491 MonoClass *nested = access_class->nested_in;
10493 can = can_access_type (nested, member_class);
10496 nested = nested->nested_in;
10503 if (called->is_inflated) {
10504 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10505 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10514 * mono_method_can_access_field_full:
10515 * @method: The caller method
10516 * @field: The accessed field
10517 * @context_klass: The static type on stack of the owner @field object used
10519 * This function must be used with instance fields, as they have more strict family accessibility.
10520 * It can be used with static fields, but context_klass should be NULL.
10522 * Returns: TRUE if caller have proper visibility and acessibility to @field
10525 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10527 MonoClass *access_class = method->klass;
10528 MonoClass *member_class = field->parent;
10529 /* FIXME: check all overlapping fields */
10530 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10532 MonoClass *nested = access_class->nested_in;
10534 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10537 nested = nested->nested_in;
10544 can = can_access_type (access_class, member_class);
10546 MonoClass *nested = access_class->nested_in;
10548 can = can_access_type (nested, member_class);
10551 nested = nested->nested_in;
10561 * mono_class_can_access_class:
10562 * @source_class: The source class
10563 * @target_class: The accessed class
10565 * This function returns is @target_class is visible to @source_class
10567 * Returns: TRUE if source have proper visibility and acessibility to target
10570 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10572 return can_access_type (source_class, target_class);
10576 * mono_type_is_valid_enum_basetype:
10577 * @type: The MonoType to check
10579 * Returns: TRUE if the type can be used as the basetype of an enum
10581 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10582 switch (type->type) {
10585 case MONO_TYPE_BOOLEAN:
10588 case MONO_TYPE_CHAR:
10602 * mono_class_is_valid_enum:
10603 * @klass: An enum class to be validated
10605 * This method verify the required properties an enum should have.
10607 * Returns: TRUE if the informed enum class is valid
10609 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10610 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10611 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10614 mono_class_is_valid_enum (MonoClass *klass)
10616 MonoClassField * field;
10617 gpointer iter = NULL;
10618 gboolean found_base_field = FALSE;
10620 g_assert (klass->enumtype);
10621 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10622 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10626 if (!mono_class_is_auto_layout (klass))
10629 while ((field = mono_class_get_fields (klass, &iter))) {
10630 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10631 if (found_base_field)
10633 found_base_field = TRUE;
10634 if (!mono_type_is_valid_enum_basetype (field->type))
10639 if (!found_base_field)
10642 if (mono_class_get_method_count (klass) > 0)
10649 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10651 return gklass->context.class_inst == mono_class_get_generic_container (gklass->container_class)->context.class_inst;
10655 * mono_class_setup_interface_id:
10657 * Initializes MonoClass::interface_id if required.
10659 * LOCKING: Acquires the loader lock.
10662 mono_class_setup_interface_id (MonoClass *klass)
10664 mono_loader_lock ();
10665 if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10666 klass->interface_id = mono_get_unique_iid (klass);
10667 mono_loader_unlock ();
10671 * mono_class_alloc_ext:
10673 * Allocate klass->ext if not already done.
10676 mono_class_alloc_ext (MonoClass *klass)
10680 if (mono_class_get_ext (klass))
10683 ext = (MonoClassExt *)mono_class_alloc0 (klass, sizeof (MonoClassExt));
10684 mono_image_lock (klass->image);
10685 mono_memory_barrier ();
10686 if (!mono_class_get_ext (klass))
10687 mono_class_set_ext (klass, ext);
10688 class_ext_size += sizeof (MonoClassExt);
10690 mono_image_unlock (klass->image);
10694 * mono_class_setup_interfaces:
10696 * Initialize klass->interfaces/interfaces_count.
10697 * LOCKING: Acquires the loader lock.
10698 * This function can fail the type.
10701 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10703 int i, interface_count;
10704 MonoClass **interfaces;
10706 mono_error_init (error);
10708 if (klass->interfaces_inited)
10711 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10712 MonoType *args [1];
10714 /* generic IList, ICollection, IEnumerable */
10715 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10716 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10718 args [0] = &klass->element_class->byval_arg;
10719 interfaces [0] = mono_class_bind_generic_parameters (
10720 mono_defaults.generic_ilist_class, 1, args, FALSE);
10721 if (interface_count > 1)
10722 interfaces [1] = mono_class_bind_generic_parameters (
10723 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10724 } else if (mono_class_is_ginst (klass)) {
10725 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
10727 mono_class_setup_interfaces (gklass, error);
10728 if (!mono_error_ok (error)) {
10729 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10733 interface_count = gklass->interface_count;
10734 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10735 for (i = 0; i < interface_count; i++) {
10736 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (mono_class_get_generic_class (klass)), error);
10737 if (!mono_error_ok (error)) {
10738 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10743 interface_count = 0;
10747 mono_image_lock (klass->image);
10749 if (!klass->interfaces_inited) {
10750 klass->interface_count = interface_count;
10751 klass->interfaces = interfaces;
10753 mono_memory_barrier ();
10755 klass->interfaces_inited = TRUE;
10758 mono_image_unlock (klass->image);
10762 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10764 MonoClass *klass = field->parent;
10765 MonoImage *image = klass->image;
10766 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10768 int field_idx = field - klass->fields;
10770 mono_error_init (error);
10773 MonoClassField *gfield = >d->fields [field_idx];
10774 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10775 if (!mono_error_ok (error)) {
10776 char *full_name = mono_type_get_full_name (gtd);
10777 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));
10778 g_free (full_name);
10781 ftype = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10782 if (!mono_error_ok (error)) {
10783 char *full_name = mono_type_get_full_name (klass);
10784 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));
10785 g_free (full_name);
10789 guint32 cols [MONO_FIELD_SIZE];
10790 MonoGenericContainer *container = NULL;
10791 int idx = mono_class_get_first_field_idx (klass) + field_idx;
10793 /*FIXME, in theory we do not lazy load SRE fields*/
10794 g_assert (!image_is_dynamic (image));
10796 if (mono_class_is_gtd (klass)) {
10797 container = mono_class_get_generic_container (klass);
10799 container = mono_class_get_generic_container (gtd);
10800 g_assert (container);
10803 /* first_field_idx and idx points into the fieldptr table */
10804 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10806 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10807 char *full_name = mono_type_get_full_name (klass);
10808 mono_error_set_type_load_class (error, klass, "Could not verify field '%s:%s' signature", full_name, field->name);;
10809 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
10810 g_free (full_name);
10814 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10816 mono_metadata_decode_value (sig, &sig);
10817 /* FIELD signature == 0x06 */
10818 g_assert (*sig == 0x06);
10820 ftype = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10822 char *full_name = mono_type_get_full_name (klass);
10823 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));
10824 g_free (full_name);
10827 mono_memory_barrier ();
10828 field->type = ftype;
10832 mono_field_resolve_flags (MonoClassField *field)
10834 MonoClass *klass = field->parent;
10835 MonoImage *image = klass->image;
10836 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10837 int field_idx = field - klass->fields;
10841 MonoClassField *gfield = >d->fields [field_idx];
10842 return mono_field_get_flags (gfield);
10844 int idx = mono_class_get_first_field_idx (klass) + field_idx;
10846 /*FIXME, in theory we do not lazy load SRE fields*/
10847 g_assert (!image_is_dynamic (image));
10849 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10854 * mono_class_get_fields_lazy:
10855 * @klass: the MonoClass to act on
10857 * This routine is an iterator routine for retrieving the fields in a class.
10858 * Only minimal information about fields are loaded. Accessors must be used
10859 * for all MonoClassField returned.
10861 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10862 * iterate over all of the elements. When no more values are
10863 * available, the return value is NULL.
10865 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10868 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10870 MonoClassField* field;
10874 mono_class_setup_basic_field_info (klass);
10875 if (!klass->fields)
10877 /* start from the first */
10878 if (mono_class_get_field_count (klass)) {
10879 *iter = &klass->fields [0];
10880 return (MonoClassField *)*iter;
10886 field = (MonoClassField *)*iter;
10888 if (field < &klass->fields [mono_class_get_field_count (klass)]) {
10890 return (MonoClassField *)*iter;
10896 mono_class_full_name (MonoClass *klass)
10898 return mono_type_full_name (&klass->byval_arg);
10901 /* Declare all shared lazy type lookup functions */
10902 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, System.Runtime.InteropServices, SafeHandle)