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)
19 #include <mono/metadata/image.h>
20 #include <mono/metadata/assembly.h>
21 #include <mono/metadata/metadata.h>
22 #include <mono/metadata/metadata-internals.h>
23 #include <mono/metadata/profiler-private.h>
24 #include <mono/metadata/tabledefs.h>
25 #include <mono/metadata/tokentype.h>
26 #include <mono/metadata/class-internals.h>
27 #include <mono/metadata/object.h>
28 #include <mono/metadata/appdomain.h>
29 #include <mono/metadata/mono-endian.h>
30 #include <mono/metadata/debug-helpers.h>
31 #include <mono/metadata/reflection.h>
32 #include <mono/metadata/exception.h>
33 #include <mono/metadata/security-manager.h>
34 #include <mono/metadata/security-core-clr.h>
35 #include <mono/metadata/attrdefs.h>
36 #include <mono/metadata/gc-internals.h>
37 #include <mono/metadata/verify-internals.h>
38 #include <mono/metadata/mono-debug.h>
39 #include <mono/utils/mono-counters.h>
40 #include <mono/utils/mono-string.h>
41 #include <mono/utils/mono-error-internals.h>
42 #include <mono/utils/mono-logger-internals.h>
43 #include <mono/utils/mono-memory-model.h>
44 #include <mono/utils/atomic.h>
45 #include <mono/utils/bsearch.h>
46 #include <mono/utils/checked-build.h>
50 gboolean mono_print_vtable = FALSE;
51 gboolean mono_align_small_structs = FALSE;
54 guint32 inflated_classes, inflated_classes_size, inflated_methods_size;
55 guint32 classes_size, class_ext_size;
57 /* Low level lock which protects data structures in this module */
58 static mono_mutex_t classes_mutex;
60 /* Function supplied by the runtime to find classes by name using information from the AOT file */
61 static MonoGetClassFromName get_class_from_name = NULL;
63 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error);
64 static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
65 static gboolean can_access_type (MonoClass *access_klass, MonoClass *member_klass);
66 static MonoMethod* find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags);
67 static int generic_array_methods (MonoClass *klass);
68 static void setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos);
70 static MonoMethod* mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter);
71 static char* mono_assembly_name_from_token (MonoImage *image, guint32 type_token);
72 static void mono_field_resolve_type (MonoClassField *field, MonoError *error);
73 static guint32 mono_field_resolve_flags (MonoClassField *field);
74 static void mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup);
75 static void mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gklass);
78 We use gclass recording to allow recursive system f types to be referenced by a parent.
80 Given the following type hierarchy:
82 class TextBox : TextBoxBase<TextBox> {}
83 class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
84 class TextInput<T> : Input<T> where T: TextInput<T> {}
87 The runtime tries to load TextBoxBase<>.
88 To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
89 To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
90 To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
92 At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded
93 at this point, iow, both are registered in the type map and both and a NULL parent. This means
94 that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
96 To fix that what we do is to record all generic instantes created while resolving the parent of
97 any generic type definition and, after resolved, correct the parent field if needed.
100 static int record_gclass_instantiation;
101 static GSList *gclass_recorded_list;
102 typedef gboolean (*gclass_record_func) (MonoClass*, void*);
107 mono_locks_os_acquire (&classes_mutex, ClassesLock);
111 classes_unlock (void)
113 mono_locks_os_release (&classes_mutex, ClassesLock);
117 * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
120 enable_gclass_recording (void)
122 ++record_gclass_instantiation;
126 * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
129 disable_gclass_recording (gclass_record_func func, void *user_data)
131 GSList **head = &gclass_recorded_list;
133 g_assert (record_gclass_instantiation > 0);
134 --record_gclass_instantiation;
137 GSList *node = *head;
138 if (func ((MonoClass*)node->data, user_data)) {
140 g_slist_free_1 (node);
146 /* We automatically discard all recorded gclasses when disabled. */
147 if (!record_gclass_instantiation && gclass_recorded_list) {
148 g_slist_free (gclass_recorded_list);
149 gclass_recorded_list = NULL;
154 * mono_class_from_typeref:
155 * @image: a MonoImage
156 * @type_token: a TypeRef token
158 * Creates the MonoClass* structure representing the type defined by
159 * the typeref token valid inside @image.
160 * Returns: The MonoClass* representing the typeref token, NULL ifcould
164 mono_class_from_typeref (MonoImage *image, guint32 type_token)
167 MonoClass *klass = mono_class_from_typeref_checked (image, type_token, &error);
168 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
173 * mono_class_from_typeref_checked:
174 * @image: a MonoImage
175 * @type_token: a TypeRef token
176 * @error: error return code, if any.
178 * Creates the MonoClass* structure representing the type defined by
179 * the typeref token valid inside @image.
181 * Returns: The MonoClass* representing the typeref token, NULL if it could
182 * not be loaded with the @error value filled with the information about the
186 mono_class_from_typeref_checked (MonoImage *image, guint32 type_token, MonoError *error)
188 guint32 cols [MONO_TYPEREF_SIZE];
189 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
191 const char *name, *nspace;
192 MonoClass *res = NULL;
195 mono_error_init (error);
197 if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, error))
200 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
202 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
203 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
205 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
206 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
207 case MONO_RESOLUTION_SCOPE_MODULE:
209 LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
210 This is not the observed behavior of existing implementations.
211 The defacto behavior is that it's just a typedef in disguise.
213 /* a typedef in disguise */
214 res = mono_class_from_name_checked (image, nspace, name, error);
217 case MONO_RESOLUTION_SCOPE_MODULEREF:
218 module = mono_image_load_module (image, idx);
220 res = mono_class_from_name_checked (module, nspace, name, error);
223 case MONO_RESOLUTION_SCOPE_TYPEREF: {
224 MonoClass *enclosing;
227 if (idx == mono_metadata_token_index (type_token)) {
228 mono_error_set_bad_image (error, image, "Image with self-referencing typeref token %08x.", type_token);
232 enclosing = mono_class_from_typeref_checked (image, MONO_TOKEN_TYPE_REF | idx, error);
233 return_val_if_nok (error, NULL);
235 if (enclosing->nested_classes_inited && enclosing->ext) {
236 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
237 for (tmp = enclosing->ext->nested_classes; tmp; tmp = tmp->next) {
238 res = (MonoClass *)tmp->data;
239 if (strcmp (res->name, name) == 0)
243 /* Don't call mono_class_init as we might've been called by it recursively */
244 int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
246 guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
247 guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
248 const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
250 if (strcmp (nname, name) == 0)
251 return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, error);
253 i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
256 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name);
259 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
263 if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) {
264 mono_error_set_bad_image (error, image, "Image with invalid assemblyref token %08x.", idx);
268 if (!image->references || !image->references [idx - 1])
269 mono_assembly_load_reference (image, idx - 1);
270 g_assert (image->references [idx - 1]);
272 /* If the assembly did not load, register this as a type load exception */
273 if (image->references [idx - 1] == REFERENCE_MISSING){
274 MonoAssemblyName aname;
277 mono_assembly_get_assemblyref (image, idx - 1, &aname);
278 human_name = mono_stringify_assembly_name (&aname);
279 mono_error_set_assembly_load_simple (error, human_name, image->assembly ? image->assembly->ref_only : FALSE);
283 res = mono_class_from_name_checked (image->references [idx - 1]->image, nspace, name, error);
286 /* Generic case, should be avoided for when a better error is possible. */
287 if (!res && mono_error_ok (error)) {
288 if (mono_loader_get_last_error ()) { /*FIXME plug the above to not leak errors*/
289 mono_error_set_from_loader_error (error);
291 char *name = mono_class_name_from_token (image, type_token);
292 char *assembly = mono_assembly_name_from_token (image, type_token);
293 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
296 mono_loader_assert_no_error ();
302 mono_image_memdup (MonoImage *image, void *data, guint size)
304 void *res = mono_image_alloc (image, size);
305 memcpy (res, data, size);
309 /* Copy everything mono_metadata_free_array free. */
311 mono_dup_array_type (MonoImage *image, MonoArrayType *a)
314 a = (MonoArrayType *)mono_image_memdup (image, a, sizeof (MonoArrayType));
316 a->sizes = (int *)mono_image_memdup (image, a->sizes, a->numsizes * sizeof (int));
318 a->lobounds = (int *)mono_image_memdup (image, a->lobounds, a->numlobounds * sizeof (int));
320 a = (MonoArrayType *)g_memdup (a, sizeof (MonoArrayType));
322 a->sizes = (int *)g_memdup (a->sizes, a->numsizes * sizeof (int));
324 a->lobounds = (int *)g_memdup (a->lobounds, a->numlobounds * sizeof (int));
329 /* Copy everything mono_metadata_free_method_signature free. */
331 mono_metadata_signature_deep_dup (MonoImage *image, MonoMethodSignature *sig)
335 sig = mono_metadata_signature_dup_full (image, sig);
337 sig->ret = mono_metadata_type_dup (image, sig->ret);
338 for (i = 0; i < sig->param_count; ++i)
339 sig->params [i] = mono_metadata_type_dup (image, sig->params [i]);
345 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
347 MonoAssembly *ta = klass->image->assembly;
350 name = mono_stringify_assembly_name (&ta->aname);
351 g_string_append_printf (str, ", %s", name);
356 mono_type_name_check_byref (MonoType *type, GString *str)
359 g_string_append_c (str, '&');
363 * mono_identifier_escape_type_name_chars:
364 * @str: a destination string
365 * @identifier: an IDENTIFIER in internal form
369 * The displayed form of the identifier is appended to str.
371 * The displayed form of an identifier has the characters ,+&*[]\
372 * that have special meaning in type names escaped with a preceeding
373 * backslash (\) character.
376 mono_identifier_escape_type_name_chars (GString* str, const char* identifier)
382 // reserve space for common case: there will be no escaped characters.
383 g_string_set_size(str, n + strlen(identifier));
384 g_string_set_size(str, n);
386 for (const char* s = identifier; *s != 0 ; s++) {
395 g_string_append_c (str, '\\');
396 g_string_append_c (str, *s);
399 g_string_append_c (str, *s);
407 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
408 MonoTypeNameFormat format)
412 switch (type->type) {
413 case MONO_TYPE_ARRAY: {
414 int i, rank = type->data.array->rank;
415 MonoTypeNameFormat nested_format;
417 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
418 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
420 mono_type_get_name_recurse (
421 &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
422 g_string_append_c (str, '[');
424 g_string_append_c (str, '*');
425 for (i = 1; i < rank; i++)
426 g_string_append_c (str, ',');
427 g_string_append_c (str, ']');
429 mono_type_name_check_byref (type, str);
431 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
432 _mono_type_get_assembly_name (type->data.array->eklass, str);
435 case MONO_TYPE_SZARRAY: {
436 MonoTypeNameFormat nested_format;
438 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
439 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
441 mono_type_get_name_recurse (
442 &type->data.klass->byval_arg, str, FALSE, nested_format);
443 g_string_append (str, "[]");
445 mono_type_name_check_byref (type, str);
447 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
448 _mono_type_get_assembly_name (type->data.klass, str);
451 case MONO_TYPE_PTR: {
452 MonoTypeNameFormat nested_format;
454 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
455 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
457 mono_type_get_name_recurse (
458 type->data.type, str, FALSE, nested_format);
459 g_string_append_c (str, '*');
461 mono_type_name_check_byref (type, str);
463 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
464 _mono_type_get_assembly_name (mono_class_from_mono_type (type->data.type), str);
469 if (!mono_generic_param_info (type->data.generic_param))
470 g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num);
472 g_string_append (str, mono_generic_param_info (type->data.generic_param)->name);
474 mono_type_name_check_byref (type, str);
478 klass = mono_class_from_mono_type (type);
479 if (klass->nested_in) {
480 mono_type_get_name_recurse (
481 &klass->nested_in->byval_arg, str, TRUE, format);
482 if (format == MONO_TYPE_NAME_FORMAT_IL)
483 g_string_append_c (str, '.');
485 g_string_append_c (str, '+');
486 } else if (*klass->name_space) {
487 if (format == MONO_TYPE_NAME_FORMAT_IL)
488 g_string_append (str, klass->name_space);
490 mono_identifier_escape_type_name_chars (str, klass->name_space);
491 g_string_append_c (str, '.');
493 if (format == MONO_TYPE_NAME_FORMAT_IL) {
494 char *s = strchr (klass->name, '`');
495 int len = s ? s - klass->name : strlen (klass->name);
496 g_string_append_len (str, klass->name, len);
498 mono_identifier_escape_type_name_chars (str, klass->name);
502 if (klass->generic_class) {
503 MonoGenericClass *gclass = klass->generic_class;
504 MonoGenericInst *inst = gclass->context.class_inst;
505 MonoTypeNameFormat nested_format;
508 nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
509 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
511 if (format == MONO_TYPE_NAME_FORMAT_IL)
512 g_string_append_c (str, '<');
514 g_string_append_c (str, '[');
515 for (i = 0; i < inst->type_argc; i++) {
516 MonoType *t = inst->type_argv [i];
519 g_string_append_c (str, ',');
520 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
521 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
522 g_string_append_c (str, '[');
523 mono_type_get_name_recurse (inst->type_argv [i], str, FALSE, nested_format);
524 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
525 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
526 g_string_append_c (str, ']');
528 if (format == MONO_TYPE_NAME_FORMAT_IL)
529 g_string_append_c (str, '>');
531 g_string_append_c (str, ']');
532 } else if (klass->generic_container &&
533 (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
534 (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
537 if (format == MONO_TYPE_NAME_FORMAT_IL)
538 g_string_append_c (str, '<');
540 g_string_append_c (str, '[');
541 for (i = 0; i < klass->generic_container->type_argc; i++) {
543 g_string_append_c (str, ',');
544 g_string_append (str, mono_generic_container_get_param_info (klass->generic_container, i)->name);
546 if (format == MONO_TYPE_NAME_FORMAT_IL)
547 g_string_append_c (str, '>');
549 g_string_append_c (str, ']');
552 mono_type_name_check_byref (type, str);
554 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
555 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
556 _mono_type_get_assembly_name (klass, str);
562 * mono_type_get_name_full:
564 * @format: the format for the return string.
567 * Returns: The string representation in a number of formats:
569 * if format is MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
570 * returned in the formatrequired by System.Reflection, this is the
571 * inverse of mono_reflection_parse_type ().
573 * if format is MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
574 * be used by the IL assembler.
576 * if format is MONO_TYPE_NAME_FORMAT_FULL_NAME
578 * if format is MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
581 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
585 result = g_string_new ("");
587 mono_type_get_name_recurse (type, result, FALSE, format);
589 return g_string_free (result, FALSE);
593 * mono_type_get_full_name:
596 * Returns: The string representation for type as required by System.Reflection.
597 * The inverse of mono_reflection_parse_type ().
600 mono_type_get_full_name (MonoClass *klass)
602 return mono_type_get_name_full (mono_class_get_type (klass), MONO_TYPE_NAME_FORMAT_REFLECTION);
606 * mono_type_get_name:
609 * Returns: The string representation for type as it would be represented in IL code.
612 mono_type_get_name (MonoType *type)
614 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
618 * mono_type_get_underlying_type:
621 * Returns: The MonoType for the underlying integer type if @type
622 * is an enum and byref is false, otherwise the type itself.
625 mono_type_get_underlying_type (MonoType *type)
627 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype && !type->byref)
628 return mono_class_enum_basetype (type->data.klass);
629 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype && !type->byref)
630 return mono_class_enum_basetype (type->data.generic_class->container_class);
635 * mono_class_is_open_constructed_type:
638 * Returns: TRUE if type represents a generics open constructed type.
639 * IOW, not all type parameters required for the instantiation have
640 * been provided or it's a generic type definition.
642 * An open constructed type means it's a non realizable type. Not to
643 * be mixed up with an abstract type - we can't cast or dispatch to
644 * an open type, for example.
647 mono_class_is_open_constructed_type (MonoType *t)
653 case MONO_TYPE_SZARRAY:
654 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
655 case MONO_TYPE_ARRAY:
656 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
658 return mono_class_is_open_constructed_type (t->data.type);
659 case MONO_TYPE_GENERICINST:
660 return t->data.generic_class->context.class_inst->is_open;
661 case MONO_TYPE_CLASS:
662 case MONO_TYPE_VALUETYPE:
663 return t->data.klass->generic_container != NULL;
670 This is a simple function to catch the most common bad instances of generic types.
671 Specially those that might lead to further failures in the runtime.
674 is_valid_generic_argument (MonoType *type)
676 switch (type->type) {
678 //case MONO_TYPE_TYPEDBYREF:
686 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
688 mono_error_init (error);
690 switch (type->type) {
691 case MONO_TYPE_MVAR: {
693 int num = mono_type_get_generic_param_num (type);
694 MonoGenericInst *inst = context->method_inst;
697 if (num >= inst->type_argc) {
698 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
699 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
700 num, info ? info->name : "", inst->type_argc);
704 if (!is_valid_generic_argument (inst->type_argv [num])) {
705 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
706 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
707 num, info ? info->name : "", inst->type_argv [num]->type);
711 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
712 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
713 * ->byref and ->attrs from @type are propagated to the returned type.
715 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
716 nt->byref = type->byref;
717 nt->attrs = type->attrs;
720 case MONO_TYPE_VAR: {
722 int num = mono_type_get_generic_param_num (type);
723 MonoGenericInst *inst = context->class_inst;
726 if (num >= inst->type_argc) {
727 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
728 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
729 num, info ? info->name : "", inst->type_argc);
732 if (!is_valid_generic_argument (inst->type_argv [num])) {
733 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
734 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
735 num, info ? info->name : "", inst->type_argv [num]->type);
738 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
739 nt->byref = type->byref;
740 nt->attrs = type->attrs;
743 case MONO_TYPE_SZARRAY: {
744 MonoClass *eclass = type->data.klass;
745 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
746 if (!inflated || !mono_error_ok (error))
748 nt = mono_metadata_type_dup (image, type);
749 nt->data.klass = mono_class_from_mono_type (inflated);
750 mono_metadata_free_type (inflated);
753 case MONO_TYPE_ARRAY: {
754 MonoClass *eclass = type->data.array->eklass;
755 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
756 if (!inflated || !mono_error_ok (error))
758 nt = mono_metadata_type_dup (image, type);
759 nt->data.array->eklass = mono_class_from_mono_type (inflated);
760 mono_metadata_free_type (inflated);
763 case MONO_TYPE_GENERICINST: {
764 MonoGenericClass *gclass = type->data.generic_class;
765 MonoGenericInst *inst;
767 if (!gclass->context.class_inst->is_open)
770 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
771 return_val_if_nok (error, NULL);
773 if (inst != gclass->context.class_inst)
774 gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
776 if (gclass == type->data.generic_class)
779 nt = mono_metadata_type_dup (image, type);
780 nt->data.generic_class = gclass;
783 case MONO_TYPE_CLASS:
784 case MONO_TYPE_VALUETYPE: {
785 MonoClass *klass = type->data.klass;
786 MonoGenericContainer *container = klass->generic_container;
787 MonoGenericInst *inst;
788 MonoGenericClass *gclass = NULL;
794 /* We can't use context->class_inst directly, since it can have more elements */
795 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
796 return_val_if_nok (error, NULL);
798 if (inst == container->context.class_inst)
801 gclass = mono_metadata_lookup_generic_class (klass, inst, image_is_dynamic (klass->image));
803 nt = mono_metadata_type_dup (image, type);
804 nt->type = MONO_TYPE_GENERICINST;
805 nt->data.generic_class = gclass;
815 mono_generic_class_get_context (MonoGenericClass *gclass)
817 return &gclass->context;
821 mono_class_get_context (MonoClass *klass)
823 return klass->generic_class ? mono_generic_class_get_context (klass->generic_class) : NULL;
827 * mono_class_get_generic_container:
829 * Return the generic container of KLASS which should be a generic type definition.
831 MonoGenericContainer*
832 mono_class_get_generic_container (MonoClass *klass)
834 g_assert (klass->is_generic);
836 return klass->generic_container;
840 * mono_class_get_generic_class:
842 * Return the MonoGenericClass of KLASS, which should be a generic instance.
845 mono_class_get_generic_class (MonoClass *klass)
847 g_assert (klass->is_inflated);
849 return klass->generic_class;
853 * mono_class_inflate_generic_type_with_mempool:
854 * @mempool: a mempool
856 * @context: a generics context
857 * @error: error context
859 * The same as mono_class_inflate_generic_type, but allocates the MonoType
860 * from mempool if it is non-NULL. If it is NULL, the MonoType is
861 * allocated on the heap and is owned by the caller.
862 * The returned type can potentially be the same as TYPE, so it should not be
863 * modified by the caller, and it should be freed using mono_metadata_free_type ().
866 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
868 MonoType *inflated = NULL;
869 mono_error_init (error);
872 inflated = inflate_generic_type (image, type, context, error);
873 return_val_if_nok (error, NULL);
876 MonoType *shared = mono_metadata_get_shared_type (type);
881 return mono_metadata_type_dup (image, type);
885 mono_stats.inflated_type_count++;
890 * mono_class_inflate_generic_type:
892 * @context: a generics context
894 * If @type is a generic type and @context is not NULL, instantiate it using the
895 * generics context @context.
897 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
898 * on the heap and is owned by the caller. Returns NULL on error.
900 * @deprecated Please use mono_class_inflate_generic_type_checked instead
903 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
907 result = mono_class_inflate_generic_type_checked (type, context, &error);
908 mono_error_cleanup (&error);
913 * mono_class_inflate_generic_type:
915 * @context: a generics context
916 * @error: error context to use
918 * If @type is a generic type and @context is not NULL, instantiate it using the
919 * generics context @context.
921 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
922 * on the heap and is owned by the caller.
925 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
927 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
931 * mono_class_inflate_generic_type_no_copy:
933 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
937 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
939 MonoType *inflated = NULL;
941 mono_error_init (error);
943 inflated = inflate_generic_type (image, type, context, error);
944 return_val_if_nok (error, NULL);
950 mono_stats.inflated_type_count++;
955 * mono_class_inflate_generic_class:
957 * Inflate the class @gklass with @context. Set @error on failure.
960 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
965 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
966 return_val_if_nok (error, NULL);
968 res = mono_class_from_mono_type (inflated);
969 mono_metadata_free_type (inflated);
974 static MonoGenericContext
975 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
977 MonoGenericInst *class_inst = NULL;
978 MonoGenericInst *method_inst = NULL;
979 MonoGenericContext res = { NULL, NULL };
981 mono_error_init (error);
983 if (context->class_inst) {
984 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
985 if (!mono_error_ok (error))
989 if (context->method_inst) {
990 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
991 if (!mono_error_ok (error))
995 res.class_inst = class_inst;
996 res.method_inst = method_inst;
1002 * mono_class_inflate_generic_method:
1003 * @method: a generic method
1004 * @context: a generics context
1006 * Instantiate the generic method @method using the generics context @context.
1008 * Returns: The new instantiated method
1011 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
1013 return mono_class_inflate_generic_method_full (method, NULL, context);
1017 mono_class_inflate_generic_method_checked (MonoMethod *method, MonoGenericContext *context, MonoError *error)
1019 return mono_class_inflate_generic_method_full_checked (method, NULL, context, error);
1023 * mono_class_inflate_generic_method_full:
1025 * Instantiate method @method with the generic context @context.
1026 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
1027 * Use mono_method_signature () and mono_method_get_header () to get the correct values.
1030 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
1033 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
1034 if (!mono_error_ok (&error))
1035 /*FIXME do proper error handling - on this case, kill this function. */
1036 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
1042 * mono_class_inflate_generic_method_full_checked:
1043 * Same as mono_class_inflate_generic_method_full but return failure using @error.
1046 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
1049 MonoMethodInflated *iresult, *cached;
1050 MonoMethodSignature *sig;
1051 MonoGenericContext tmp_context;
1053 mono_error_init (error);
1055 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1056 while (method->is_inflated) {
1057 MonoGenericContext *method_context = mono_method_get_context (method);
1058 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1060 tmp_context = inflate_generic_context (method_context, context, error);
1061 return_val_if_nok (error, NULL);
1063 context = &tmp_context;
1065 if (mono_metadata_generic_context_equal (method_context, context))
1068 method = imethod->declaring;
1072 * A method only needs to be inflated if the context has argument for which it is
1075 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1076 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1079 if (!((method->is_generic && context->method_inst) ||
1080 (method->klass->generic_container && context->class_inst)))
1083 iresult = g_new0 (MonoMethodInflated, 1);
1084 iresult->context = *context;
1085 iresult->declaring = method;
1087 if (!context->method_inst && method->is_generic)
1088 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1090 if (!context->class_inst) {
1091 g_assert (!iresult->declaring->klass->generic_class);
1092 if (iresult->declaring->klass->generic_container)
1093 iresult->context.class_inst = iresult->declaring->klass->generic_container->context.class_inst;
1094 else if (iresult->declaring->klass->generic_class)
1095 iresult->context.class_inst = iresult->declaring->klass->generic_class->context.class_inst;
1097 /* This can happen with some callers like mono_object_get_virtual_method () */
1098 if (!iresult->declaring->klass->generic_container && !iresult->declaring->klass->generic_class)
1099 iresult->context.class_inst = NULL;
1101 MonoImageSet *set = mono_metadata_get_image_set_for_method (iresult);
1104 mono_image_set_lock (set);
1105 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1106 mono_image_set_unlock (set);
1110 return (MonoMethod*)cached;
1113 mono_stats.inflated_method_count++;
1115 inflated_methods_size += sizeof (MonoMethodInflated);
1117 sig = mono_method_signature (method);
1119 char *name = mono_type_get_full_name (method->klass);
1120 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1126 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1128 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1131 result = (MonoMethod *) iresult;
1132 result->is_inflated = TRUE;
1133 result->is_generic = FALSE;
1134 result->sre_method = FALSE;
1135 result->signature = NULL;
1137 if (!context->method_inst) {
1138 /* Set the generic_container of the result to the generic_container of method */
1139 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1141 if (generic_container) {
1142 result->is_generic = 1;
1143 mono_method_set_generic_container (result, generic_container);
1147 if (!klass_hint || !klass_hint->generic_class ||
1148 klass_hint->generic_class->container_class != method->klass ||
1149 klass_hint->generic_class->context.class_inst != context->class_inst)
1152 if (method->klass->generic_container)
1153 result->klass = klass_hint;
1155 if (!result->klass) {
1156 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1157 if (!mono_error_ok (error))
1160 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1162 mono_metadata_free_type (inflated);
1166 * FIXME: This should hold, but it doesn't:
1168 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1169 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1170 * g_assert (result->is_generic);
1173 * Fixing this here causes other things to break, hence a very
1174 * ugly hack in mini-trampolines.c - see
1175 * is_generic_method_definition().
1179 mono_image_set_lock (set);
1180 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1182 g_hash_table_insert (set->gmethod_cache, iresult, iresult);
1183 iresult->owner = set;
1186 mono_image_set_unlock (set);
1188 return (MonoMethod*)cached;
1196 * mono_get_inflated_method:
1198 * Obsolete. We keep it around since it's mentioned in the public API.
1201 mono_get_inflated_method (MonoMethod *method)
1207 * mono_method_get_context_general:
1209 * @uninflated: handle uninflated methods?
1211 * Returns the generic context of a method or NULL if it doesn't have
1212 * one. For an inflated method that's the context stored in the
1213 * method. Otherwise it's in the method's generic container or in the
1214 * generic container of the method's class.
1217 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1219 if (method->is_inflated) {
1220 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1221 return &imethod->context;
1225 if (method->is_generic)
1226 return &(mono_method_get_generic_container (method)->context);
1227 if (method->klass->generic_container)
1228 return &method->klass->generic_container->context;
1233 * mono_method_get_context:
1236 * Returns the generic context for method if it's inflated, otherwise
1240 mono_method_get_context (MonoMethod *method)
1242 return mono_method_get_context_general (method, FALSE);
1246 * mono_method_get_generic_container:
1248 * Returns the generic container of METHOD, which should be a generic method definition.
1249 * Returns NULL if METHOD is not a generic method definition.
1250 * LOCKING: Acquires the loader lock.
1252 MonoGenericContainer*
1253 mono_method_get_generic_container (MonoMethod *method)
1255 MonoGenericContainer *container;
1257 if (!method->is_generic)
1260 container = (MonoGenericContainer *)mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1261 g_assert (container);
1267 * mono_method_set_generic_container:
1269 * Sets the generic container of METHOD to CONTAINER.
1270 * LOCKING: Acquires the image lock.
1273 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1275 g_assert (method->is_generic);
1277 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1281 * mono_class_find_enum_basetype:
1282 * @class: The enum class
1284 * Determine the basetype of an enum by iterating through its fields. We do this
1285 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1288 mono_class_find_enum_basetype (MonoClass *klass, MonoError *error)
1290 MonoGenericContainer *container = NULL;
1291 MonoImage *m = klass->image;
1292 const int top = klass->field.count;
1295 g_assert (klass->enumtype);
1297 mono_error_init (error);
1299 if (klass->generic_container)
1300 container = klass->generic_container;
1301 else if (klass->generic_class) {
1302 MonoClass *gklass = klass->generic_class->container_class;
1304 container = gklass->generic_container;
1305 g_assert (container);
1309 * Fetch all the field information.
1311 for (i = 0; i < top; i++){
1313 guint32 cols [MONO_FIELD_SIZE];
1314 int idx = klass->field.first + i;
1317 /* klass->field.first and idx points into the fieldptr table */
1318 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1320 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1323 if (!mono_verifier_verify_field_signature (klass->image, cols [MONO_FIELD_SIGNATURE], NULL)) {
1324 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x", cols [MONO_FIELD_SIGNATURE]);
1328 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1329 mono_metadata_decode_value (sig, &sig);
1330 /* FIELD signature == 0x06 */
1332 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig);
1336 ftype = mono_metadata_parse_type_checked (m, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
1340 if (klass->generic_class) {
1341 //FIXME do we leak here?
1342 ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (klass), error);
1343 if (!mono_error_ok (error))
1345 ftype->attrs = cols [MONO_FIELD_FLAGS];
1350 mono_error_set_type_load_class (error, klass, "Could not find base type");
1353 mono_loader_assert_no_error ();
1358 * Checks for MonoClass::exception_type without resolving all MonoType's into MonoClass'es
1361 mono_type_has_exceptions (MonoType *type)
1363 switch (type->type) {
1364 case MONO_TYPE_CLASS:
1365 case MONO_TYPE_VALUETYPE:
1366 case MONO_TYPE_SZARRAY:
1367 return mono_class_has_failure (type->data.klass);
1368 case MONO_TYPE_ARRAY:
1369 return mono_class_has_failure (type->data.array->eklass);
1370 case MONO_TYPE_GENERICINST:
1371 return mono_class_has_failure (mono_generic_class_get_class (type->data.generic_class));
1380 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1384 mono_class_alloc (MonoClass *klass, int size)
1386 if (klass->generic_class)
1387 return mono_image_set_alloc (klass->generic_class->owner, size);
1389 return mono_image_alloc (klass->image, size);
1393 mono_class_alloc0 (MonoClass *klass, int size)
1397 res = mono_class_alloc (klass, size);
1398 memset (res, 0, size);
1402 #define mono_class_new0(klass,struct_type, n_structs) \
1403 ((struct_type *) mono_class_alloc0 ((klass), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1406 * mono_class_setup_basic_field_info:
1407 * @class: The class to initialize
1409 * Initializes the klass->fields.
1410 * LOCKING: Assumes the loader lock is held.
1413 mono_class_setup_basic_field_info (MonoClass *klass)
1415 MonoClassField *field;
1423 gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
1424 image = klass->image;
1425 top = klass->field.count;
1427 if (klass->generic_class && image_is_dynamic (klass->generic_class->container_class->image) && !klass->generic_class->container_class->wastypebuilder) {
1429 * This happens when a generic instance of an unfinished generic typebuilder
1430 * is used as an element type for creating an array type. We can't initialize
1431 * the fields of this class using the fields of gklass, since gklass is not
1432 * finished yet, fields could be added to it later.
1438 mono_class_setup_basic_field_info (gtd);
1440 top = gtd->field.count;
1441 klass->field.first = gtd->field.first;
1442 klass->field.count = gtd->field.count;
1445 klass->fields = (MonoClassField *)mono_class_alloc0 (klass, sizeof (MonoClassField) * top);
1448 * Fetch all the field information.
1450 for (i = 0; i < top; i++){
1451 field = &klass->fields [i];
1452 field->parent = klass;
1455 field->name = mono_field_get_name (>d->fields [i]);
1457 int idx = klass->field.first + i;
1458 /* klass->field.first and idx points into the fieldptr table */
1459 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1460 /* The name is needed for fieldrefs */
1461 field->name = mono_metadata_string_heap (image, name_idx);
1467 * mono_class_setup_fields:
1468 * @class: The class to initialize
1470 * Initializes the klass->fields.
1471 * LOCKING: Assumes the loader lock is held.
1474 mono_class_setup_fields (MonoClass *klass)
1477 MonoImage *m = klass->image;
1479 guint32 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1480 int i, blittable = TRUE;
1481 guint32 real_size = 0;
1482 guint32 packing_size = 0;
1483 gboolean explicit_size;
1484 MonoClassField *field;
1485 MonoGenericContainer *container = NULL;
1486 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
1489 * FIXME: We have a race condition here. It's possible that this function returns
1490 * to its caller with `instance_size` set to `0` instead of the actual size. This
1491 * is not a problem when the function is called recursively on the same class,
1492 * because the size will be initialized by the outer invocation. What follows is a
1493 * description of how it can occur in other cases, too. There it is a problem,
1494 * because it can lead to the GC being asked to allocate an object of size `0`,
1495 * which SGen chokes on. The race condition is triggered infrequently by
1496 * `tests/sgen-suspend.cs`.
1498 * This function is called for a class whenever one of its subclasses is inited.
1499 * For example, it's called for every subclass of Object. What it does is this:
1501 * if (klass->setup_fields_called)
1504 * klass->instance_size = 0;
1506 * klass->setup_fields_called = 1;
1507 * ... critical point
1508 * klass->instance_size = actual_instance_size;
1510 * The last two steps are sometimes reversed, but that only changes the way in which
1511 * the race condition works.
1513 * Assume thread A goes through this function and makes it to the critical point.
1514 * Now thread B runs the function and, since `setup_fields_called` is set, returns
1515 * immediately, but `instance_size` is incorrect.
1517 * The other case looks like this:
1519 * if (klass->setup_fields_called)
1521 * ... critical point X
1522 * klass->instance_size = 0;
1523 * ... critical point Y
1524 * klass->instance_size = actual_instance_size;
1526 * klass->setup_fields_called = 1;
1528 * Assume thread A goes through the function and makes it to critical point X. Now
1529 * thread B runs through the whole of the function, returning, assuming
1530 * `instance_size` is set. At that point thread A gets to run and makes it to
1531 * critical point Y, at which time `instance_size` is `0` again, invalidating thread
1534 if (klass->setup_fields_called)
1537 if (klass->generic_class && image_is_dynamic (klass->generic_class->container_class->image) && !klass->generic_class->container_class->wastypebuilder) {
1539 * This happens when a generic instance of an unfinished generic typebuilder
1540 * is used as an element type for creating an array type. We can't initialize
1541 * the fields of this class using the fields of gklass, since gklass is not
1542 * finished yet, fields could be added to it later.
1547 mono_class_setup_basic_field_info (klass);
1548 top = klass->field.count;
1551 mono_class_setup_fields (gtd);
1552 if (mono_class_has_failure (gtd)) {
1553 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1558 klass->instance_size = 0;
1560 klass->sizes.class_size = 0;
1562 if (klass->parent) {
1563 /* For generic instances, klass->parent might not have been initialized */
1564 mono_class_init (klass->parent);
1565 if (!klass->parent->size_inited) {
1566 mono_class_setup_fields (klass->parent);
1567 if (mono_class_has_failure (klass->parent)) {
1568 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1572 klass->instance_size += klass->parent->instance_size;
1573 klass->min_align = klass->parent->min_align;
1574 /* we use |= since it may have been set already */
1575 klass->has_references |= klass->parent->has_references;
1576 blittable = klass->parent->blittable;
1578 klass->instance_size = sizeof (MonoObject);
1579 klass->min_align = 1;
1582 /* We can't really enable 16 bytes alignment until the GC supports it.
1583 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1584 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1585 Bug #506144 is an example of this issue.
1587 if (klass->simd_type)
1588 klass->min_align = 16;
1590 /* Get the real size */
1591 explicit_size = mono_metadata_packing_from_typedef (klass->image, klass->type_token, &packing_size, &real_size);
1593 if (explicit_size) {
1594 if ((packing_size & 0xffffff00) != 0) {
1595 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, packing_size);
1596 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
1599 klass->packing_size = packing_size;
1600 real_size += klass->instance_size;
1604 if (explicit_size && real_size) {
1605 klass->instance_size = MAX (real_size, klass->instance_size);
1607 klass->blittable = blittable;
1608 mono_memory_barrier ();
1609 klass->size_inited = 1;
1610 klass->fields_inited = 1;
1611 klass->setup_fields_called = 1;
1615 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(mono_is_corlib_image (klass->image) && !strcmp (klass->name_space, "System") && !strcmp (klass->name, "ValueType")))
1618 /* Prevent infinite loops if the class references itself */
1619 klass->setup_fields_called = 1;
1621 if (klass->generic_container) {
1622 container = klass->generic_container;
1624 container = gtd->generic_container;
1625 g_assert (container);
1629 * Fetch all the field information.
1631 for (i = 0; i < top; i++){
1632 int idx = klass->field.first + i;
1633 field = &klass->fields [i];
1635 field->parent = klass;
1638 mono_field_resolve_type (field, &error);
1639 if (!mono_error_ok (&error)) {
1640 /*mono_field_resolve_type already failed class*/
1641 mono_error_cleanup (&error);
1645 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(klass), field->name);
1646 g_assert (field->type);
1649 if (mono_field_is_deleted (field))
1652 MonoClassField *gfield = >d->fields [i];
1653 field->offset = gfield->offset;
1655 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1657 mono_metadata_field_info (m, idx, &offset, NULL, NULL);
1658 field->offset = offset;
1660 if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1661 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Missing field layout info for %s", field->name));
1664 if (field->offset < -1) { /*-1 is used to encode special static fields */
1665 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Invalid negative field offset %d for %s", field->offset, field->name));
1668 if (klass->generic_container) {
1669 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic class cannot have explicit layout."));
1675 /* Only do these checks if we still think this type is blittable */
1676 if (blittable && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1677 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1680 MonoClass *field_class = mono_class_from_mono_type (field->type);
1682 mono_class_setup_fields (field_class);
1683 if (mono_class_has_failure (field_class)) {
1684 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1688 if (!field_class || !field_class->blittable)
1693 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1694 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
1695 blittable = klass->element_class->blittable;
1698 if (mono_type_has_exceptions (field->type)) {
1699 char *class_name = mono_type_get_full_name (klass);
1700 char *type_name = mono_type_full_name (field->type);
1702 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1703 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1704 g_free (class_name);
1708 /* The def_value of fields is compute lazily during vtable creation */
1711 if (klass == mono_defaults.string_class)
1714 klass->blittable = blittable;
1716 if (klass->enumtype && !mono_class_enum_basetype (klass)) {
1717 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1720 if (explicit_size && real_size) {
1721 klass->instance_size = MAX (real_size, klass->instance_size);
1724 if (mono_class_has_failure (klass))
1726 mono_class_layout_fields (klass);
1728 /*valuetypes can't be neither bigger than 1Mb or empty. */
1729 if (klass->valuetype && (klass->instance_size <= 0 || klass->instance_size > (0x100000 + sizeof (MonoObject))))
1730 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1732 mono_memory_barrier ();
1733 klass->fields_inited = 1;
1737 * mono_class_setup_fields_locking:
1738 * @class: The class to initialize
1740 * Initializes the klass->fields array of fields.
1741 * Aquires the loader lock.
1744 mono_class_setup_fields_locking (MonoClass *klass)
1746 /* This can be checked without locks */
1747 if (klass->fields_inited)
1749 mono_loader_lock ();
1750 mono_class_setup_fields (klass);
1751 mono_loader_unlock ();
1755 * mono_class_has_references:
1757 * Returns whenever @klass->has_references is set, initializing it if needed.
1758 * Aquires the loader lock.
1761 mono_class_has_references (MonoClass *klass)
1763 if (klass->init_pending) {
1764 /* Be conservative */
1767 mono_class_init (klass);
1769 return klass->has_references;
1774 * mono_type_get_basic_type_from_generic:
1777 * Returns a closed type corresponding to the possibly open type
1781 mono_type_get_basic_type_from_generic (MonoType *type)
1783 /* When we do generic sharing we let type variables stand for reference/primitive types. */
1784 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) &&
1785 (!type->data.generic_param->gshared_constraint || type->data.generic_param->gshared_constraint->type == MONO_TYPE_OBJECT))
1786 return &mono_defaults.object_class->byval_arg;
1791 type_has_references (MonoClass *klass, MonoType *ftype)
1793 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (klass, ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1795 if (!ftype->byref && (ftype->type == MONO_TYPE_VAR || ftype->type == MONO_TYPE_MVAR)) {
1796 MonoGenericParam *gparam = ftype->data.generic_param;
1798 if (gparam->gshared_constraint)
1799 return mono_class_has_references (mono_class_from_mono_type (gparam->gshared_constraint));
1805 * mono_class_layout_fields:
1808 * Compute the placement of fields inside an object or struct, according to
1809 * the layout rules and set the following fields in @class:
1810 * - has_references (if the class contains instance references firled or structs that contain references)
1811 * - has_static_refs (same, but for static fields)
1812 * - instance_size (size of the object in memory)
1813 * - class_size (size needed for the static fields)
1814 * - size_inited (flag set when the instance_size is set)
1816 * LOCKING: this is supposed to be called with the loader lock held.
1819 mono_class_layout_fields (MonoClass *klass)
1822 const int top = klass->field.count;
1823 guint32 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1824 guint32 pass, passes, real_size;
1825 gboolean gc_aware_layout = FALSE;
1826 gboolean has_static_fields = FALSE;
1827 MonoClassField *field;
1830 * When we do generic sharing we need to have layout
1831 * information for open generic classes (either with a generic
1832 * context containing type variables or with a generic
1833 * container), so we don't return in that case anymore.
1837 * Enable GC aware auto layout: in this mode, reference
1838 * fields are grouped together inside objects, increasing collector
1840 * Requires that all classes whose layout is known to native code be annotated
1841 * with [StructLayout (LayoutKind.Sequential)]
1842 * Value types have gc_aware_layout disabled by default, as per
1843 * what the default is for other runtimes.
1845 /* corlib is missing [StructLayout] directives in many places */
1846 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1847 if (!klass->valuetype)
1848 gc_aware_layout = TRUE;
1851 /* Compute klass->has_references */
1853 * Process non-static fields first, since static fields might recursively
1854 * refer to the class itself.
1856 for (i = 0; i < top; i++) {
1859 field = &klass->fields [i];
1861 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1862 ftype = mono_type_get_underlying_type (field->type);
1863 ftype = mono_type_get_basic_type_from_generic (ftype);
1864 if (type_has_references (klass, ftype))
1865 klass->has_references = TRUE;
1869 for (i = 0; i < top; i++) {
1872 field = &klass->fields [i];
1874 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1875 ftype = mono_type_get_underlying_type (field->type);
1876 ftype = mono_type_get_basic_type_from_generic (ftype);
1877 if (type_has_references (klass, ftype))
1878 klass->has_static_refs = TRUE;
1882 for (i = 0; i < top; i++) {
1885 field = &klass->fields [i];
1887 ftype = mono_type_get_underlying_type (field->type);
1888 ftype = mono_type_get_basic_type_from_generic (ftype);
1889 if (type_has_references (klass, ftype)) {
1890 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1891 klass->has_static_refs = TRUE;
1893 klass->has_references = TRUE;
1898 * Compute field layout and total size (not considering static fields)
1902 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1903 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1905 if (gc_aware_layout)
1910 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1913 if (klass->parent) {
1914 mono_class_setup_fields (klass->parent);
1915 if (mono_class_has_failure (klass->parent)) {
1916 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1919 real_size = klass->parent->instance_size;
1921 real_size = sizeof (MonoObject);
1924 for (pass = 0; pass < passes; ++pass) {
1925 for (i = 0; i < top; i++){
1930 field = &klass->fields [i];
1932 if (mono_field_is_deleted (field))
1934 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1937 ftype = mono_type_get_underlying_type (field->type);
1938 ftype = mono_type_get_basic_type_from_generic (ftype);
1939 if (gc_aware_layout) {
1940 if (type_has_references (klass, ftype)) {
1949 if ((top == 1) && (klass->instance_size == sizeof (MonoObject)) &&
1950 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1951 /* This field is a hack inserted by MCS to empty structures */
1955 size = mono_type_size (field->type, &align);
1957 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1958 align = klass->packing_size ? MIN (klass->packing_size, align): align;
1959 /* if the field has managed references, we need to force-align it
1962 if (type_has_references (klass, ftype))
1963 align = MAX (align, sizeof (gpointer));
1965 klass->min_align = MAX (align, klass->min_align);
1966 field->offset = real_size;
1968 field->offset += align - 1;
1969 field->offset &= ~(align - 1);
1971 /*TypeBuilders produce all sort of weird things*/
1972 g_assert (image_is_dynamic (klass->image) || field->offset > 0);
1973 real_size = field->offset + size;
1976 klass->instance_size = MAX (real_size, klass->instance_size);
1978 if (klass->instance_size & (klass->min_align - 1)) {
1979 klass->instance_size += klass->min_align - 1;
1980 klass->instance_size &= ~(klass->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 = klass->packing_size ? MIN (klass->packing_size, align): align;
2006 klass->min_align = MAX (align, klass->min_align);
2009 * When we get here, field->offset is already set by the
2010 * loader (for either runtime fields or fields loaded from metadata).
2011 * The offset is from the start of the object: this works for both
2012 * classes and valuetypes.
2014 field->offset += sizeof (MonoObject);
2015 ftype = mono_type_get_underlying_type (field->type);
2016 ftype = mono_type_get_basic_type_from_generic (ftype);
2017 if (type_has_references (klass, ftype)) {
2018 if (field->offset % sizeof (gpointer)) {
2019 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
2026 real_size = MAX (real_size, size + field->offset);
2029 if (klass->has_references) {
2030 ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
2032 /* Check for overlapping reference and non-reference fields */
2033 for (i = 0; i < top; i++) {
2036 field = &klass->fields [i];
2038 if (mono_field_is_deleted (field))
2040 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2042 ftype = mono_type_get_underlying_type (field->type);
2043 if (MONO_TYPE_IS_REFERENCE (ftype))
2044 ref_bitmap [field->offset / sizeof (gpointer)] = 1;
2046 for (i = 0; i < top; i++) {
2047 field = &klass->fields [i];
2049 if (mono_field_is_deleted (field))
2051 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2054 // FIXME: Too much code does this
2056 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field->offset / sizeof (gpointer)]) {
2057 char *err_msg = g_strdup_printf ("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->offset);
2058 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
2062 g_free (ref_bitmap);
2065 klass->instance_size = MAX (real_size, klass->instance_size);
2066 if (klass->instance_size & (klass->min_align - 1)) {
2067 klass->instance_size += klass->min_align - 1;
2068 klass->instance_size &= ~(klass->min_align - 1);
2074 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2076 * This leads to all kinds of problems with nested structs, so only
2077 * enable it when a MONO_DEBUG property is set.
2079 * For small structs, set min_align to at least the struct size to improve
2080 * performance, and since the JIT memset/memcpy code assumes this and generates
2081 * unaligned accesses otherwise. See #78990 for a testcase.
2083 if (mono_align_small_structs) {
2084 if (klass->instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2085 klass->min_align = MAX (klass->min_align, klass->instance_size - sizeof (MonoObject));
2089 mono_memory_barrier ();
2090 klass->size_inited = 1;
2093 * Compute static field layout and size
2095 for (i = 0; i < top; i++){
2099 field = &klass->fields [i];
2101 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2103 if (mono_field_is_deleted (field))
2106 if (mono_type_has_exceptions (field->type)) {
2107 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
2111 has_static_fields = TRUE;
2113 size = mono_type_size (field->type, &align);
2114 field->offset = klass->sizes.class_size;
2115 /*align is always non-zero here*/
2116 field->offset += align - 1;
2117 field->offset &= ~(align - 1);
2118 klass->sizes.class_size = field->offset + size;
2121 if (has_static_fields && klass->sizes.class_size == 0)
2122 /* Simplify code which depends on class_size != 0 if the class has static fields */
2123 klass->sizes.class_size = 8;
2127 create_array_method (MonoClass *klass, const char *name, MonoMethodSignature *sig)
2131 method = (MonoMethod *) mono_image_alloc0 (klass->image, sizeof (MonoMethodPInvoke));
2132 method->klass = klass;
2133 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2134 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2135 method->signature = sig;
2136 method->name = name;
2139 if (name [0] == '.') {
2140 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2142 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2148 * mono_class_setup_methods:
2151 * Initializes the 'methods' array in CLASS.
2152 * Calling this method should be avoided if possible since it allocates a lot
2153 * of long-living MonoMethod structures.
2154 * Methods belonging to an interface are assigned a sequential slot starting
2157 * On failure this function sets klass->exception_type
2160 mono_class_setup_methods (MonoClass *klass)
2163 MonoMethod **methods;
2168 if (klass->generic_class) {
2170 MonoClass *gklass = klass->generic_class->container_class;
2172 mono_class_init (gklass);
2173 if (!mono_class_has_failure (gklass))
2174 mono_class_setup_methods (gklass);
2175 if (mono_class_has_failure (gklass)) {
2176 /* FIXME make exception_data less opaque so it's possible to dup it here */
2177 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2181 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2182 count = gklass->method.count;
2183 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * (count + 1));
2185 for (i = 0; i < count; i++) {
2186 methods [i] = mono_class_inflate_generic_method_full_checked (
2187 gklass->methods [i], klass, mono_class_get_context (klass), &error);
2188 if (!mono_error_ok (&error)) {
2189 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2190 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Could not inflate method %s due to %s", method, mono_error_get_message (&error)));
2193 mono_error_cleanup (&error);
2197 } else if (klass->rank) {
2199 MonoMethod *amethod;
2200 MonoMethodSignature *sig;
2201 int count_generic = 0, first_generic = 0;
2203 gboolean jagged_ctor = FALSE;
2205 count = 3 + (klass->rank > 1? 2: 1);
2207 mono_class_setup_interfaces (klass, &error);
2208 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2210 if (klass->rank == 1 && klass->element_class->rank) {
2212 klass->method.count ++;
2215 if (klass->interface_count) {
2216 count_generic = generic_array_methods (klass);
2217 first_generic = count;
2218 count += klass->interface_count * count_generic;
2221 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * count);
2223 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2224 sig->ret = &mono_defaults.void_class->byval_arg;
2225 sig->pinvoke = TRUE;
2226 sig->hasthis = TRUE;
2227 for (i = 0; i < klass->rank; ++i)
2228 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2230 amethod = create_array_method (klass, ".ctor", sig);
2231 methods [method_num++] = amethod;
2232 if (klass->rank > 1) {
2233 sig = mono_metadata_signature_alloc (klass->image, klass->rank * 2);
2234 sig->ret = &mono_defaults.void_class->byval_arg;
2235 sig->pinvoke = TRUE;
2236 sig->hasthis = TRUE;
2237 for (i = 0; i < klass->rank * 2; ++i)
2238 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2240 amethod = create_array_method (klass, ".ctor", sig);
2241 methods [method_num++] = amethod;
2245 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2246 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2247 sig->ret = &mono_defaults.void_class->byval_arg;
2248 sig->pinvoke = TRUE;
2249 sig->hasthis = TRUE;
2250 for (i = 0; i < klass->rank + 1; ++i)
2251 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2252 amethod = create_array_method (klass, ".ctor", sig);
2253 methods [method_num++] = amethod;
2256 /* element Get (idx11, [idx2, ...]) */
2257 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2258 sig->ret = &klass->element_class->byval_arg;
2259 sig->pinvoke = TRUE;
2260 sig->hasthis = TRUE;
2261 for (i = 0; i < klass->rank; ++i)
2262 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2263 amethod = create_array_method (klass, "Get", sig);
2264 methods [method_num++] = amethod;
2265 /* element& Address (idx11, [idx2, ...]) */
2266 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2267 sig->ret = &klass->element_class->this_arg;
2268 sig->pinvoke = TRUE;
2269 sig->hasthis = TRUE;
2270 for (i = 0; i < klass->rank; ++i)
2271 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2272 amethod = create_array_method (klass, "Address", sig);
2273 methods [method_num++] = amethod;
2274 /* void Set (idx11, [idx2, ...], element) */
2275 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2276 sig->ret = &mono_defaults.void_class->byval_arg;
2277 sig->pinvoke = TRUE;
2278 sig->hasthis = TRUE;
2279 for (i = 0; i < klass->rank; ++i)
2280 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2281 sig->params [i] = &klass->element_class->byval_arg;
2282 amethod = create_array_method (klass, "Set", sig);
2283 methods [method_num++] = amethod;
2285 for (i = 0; i < klass->interface_count; i++)
2286 setup_generic_array_ifaces (klass, klass->interfaces [i], methods, first_generic + i * count_generic);
2290 count = klass->method.count;
2291 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * count);
2292 for (i = 0; i < count; ++i) {
2293 int idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_METHOD, klass->method.first + i + 1);
2294 methods [i] = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | idx, klass, NULL, &error);
2296 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Could not load method %d due to %s", i, mono_error_get_message (&error)));
2297 mono_error_cleanup (&error);
2302 if (MONO_CLASS_IS_INTERFACE (klass)) {
2304 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2305 for (i = 0; i < count; ++i) {
2306 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2307 methods [i]->slot = slot++;
2311 mono_image_lock (klass->image);
2313 if (!klass->methods) {
2314 klass->method.count = count;
2316 /* Needed because of the double-checking locking pattern */
2317 mono_memory_barrier ();
2319 klass->methods = methods;
2322 mono_image_unlock (klass->image);
2326 * mono_class_get_method_by_index:
2328 * Returns klass->methods [index], initializing klass->methods if neccesary.
2330 * LOCKING: Acquires the loader lock.
2333 mono_class_get_method_by_index (MonoClass *klass, int index)
2336 /* Avoid calling setup_methods () if possible */
2337 if (klass->generic_class && !klass->methods) {
2338 MonoClass *gklass = klass->generic_class->container_class;
2341 m = mono_class_inflate_generic_method_full_checked (
2342 gklass->methods [index], klass, mono_class_get_context (klass), &error);
2343 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2345 * If setup_methods () is called later for this class, no duplicates are created,
2346 * since inflate_generic_method guarantees that only one instance of a method
2347 * is created for each context.
2350 mono_class_setup_methods (klass);
2351 g_assert (m == klass->methods [index]);
2355 mono_class_setup_methods (klass);
2356 if (mono_class_has_failure (klass)) /*FIXME do proper error handling*/
2358 g_assert (index >= 0 && index < klass->method.count);
2359 return klass->methods [index];
2364 * mono_class_get_inflated_method:
2366 * Given an inflated class CLASS and a method METHOD which should be a method of
2367 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2370 mono_class_get_inflated_method (MonoClass *klass, MonoMethod *method)
2372 MonoClass *gklass = klass->generic_class->container_class;
2375 g_assert (method->klass == gklass);
2377 mono_class_setup_methods (gklass);
2378 g_assert (!mono_class_has_failure (gklass)); /*FIXME do proper error handling*/
2380 for (i = 0; i < gklass->method.count; ++i) {
2381 if (gklass->methods [i] == method) {
2382 if (klass->methods) {
2383 return klass->methods [i];
2386 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], klass, mono_class_get_context (klass), &error);
2387 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2397 * mono_class_get_vtable_entry:
2399 * Returns klass->vtable [offset], computing it if neccesary. Returns NULL on failure.
2400 * LOCKING: Acquires the loader lock.
2403 mono_class_get_vtable_entry (MonoClass *klass, int offset)
2407 if (klass->rank == 1) {
2409 * szarrays do not overwrite any methods of Array, so we can avoid
2410 * initializing their vtables in some cases.
2412 mono_class_setup_vtable (klass->parent);
2413 if (offset < klass->parent->vtable_size)
2414 return klass->parent->vtable [offset];
2417 if (klass->generic_class) {
2419 MonoClass *gklass = klass->generic_class->container_class;
2420 mono_class_setup_vtable (gklass);
2421 m = gklass->vtable [offset];
2423 m = mono_class_inflate_generic_method_full_checked (m, klass, mono_class_get_context (klass), &error);
2424 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2426 mono_class_setup_vtable (klass);
2427 if (mono_class_has_failure (klass))
2429 m = klass->vtable [offset];
2436 * mono_class_get_vtable_size:
2438 * Return the vtable size for KLASS.
2441 mono_class_get_vtable_size (MonoClass *klass)
2443 mono_class_setup_vtable (klass);
2445 return klass->vtable_size;
2449 * mono_class_setup_properties:
2451 * Initialize klass->ext.property and klass->ext.properties.
2453 * This method can fail the class.
2456 mono_class_setup_properties (MonoClass *klass)
2458 guint startm, endm, i, j;
2459 guint32 cols [MONO_PROPERTY_SIZE];
2460 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2461 MonoProperty *properties;
2465 if (klass->ext && klass->ext->properties)
2468 if (klass->generic_class) {
2469 MonoClass *gklass = klass->generic_class->container_class;
2471 mono_class_init (gklass);
2472 mono_class_setup_properties (gklass);
2473 if (mono_class_has_failure (gklass)) {
2474 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2478 properties = mono_class_new0 (klass, MonoProperty, gklass->ext->property.count + 1);
2480 for (i = 0; i < gklass->ext->property.count; i++) {
2482 MonoProperty *prop = &properties [i];
2484 *prop = gklass->ext->properties [i];
2487 prop->get = mono_class_inflate_generic_method_full_checked (
2488 prop->get, klass, mono_class_get_context (klass), &error);
2490 prop->set = mono_class_inflate_generic_method_full_checked (
2491 prop->set, klass, mono_class_get_context (klass), &error);
2493 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2494 prop->parent = klass;
2497 first = gklass->ext->property.first;
2498 count = gklass->ext->property.count;
2500 first = mono_metadata_properties_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2501 count = last - first;
2504 mono_class_setup_methods (klass);
2505 if (mono_class_has_failure (klass))
2509 properties = (MonoProperty *)mono_class_alloc0 (klass, sizeof (MonoProperty) * count);
2510 for (i = first; i < last; ++i) {
2511 mono_metadata_decode_table_row (klass->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2512 properties [i - first].parent = klass;
2513 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2514 properties [i - first].name = mono_metadata_string_heap (klass->image, cols [MONO_PROPERTY_NAME]);
2516 startm = mono_metadata_methods_from_property (klass->image, i, &endm);
2517 for (j = startm; j < endm; ++j) {
2520 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2522 if (klass->image->uncompressed_metadata) {
2524 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2525 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2526 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2528 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - klass->method.first];
2531 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2532 case METHOD_SEMANTIC_SETTER:
2533 properties [i - first].set = method;
2535 case METHOD_SEMANTIC_GETTER:
2536 properties [i - first].get = method;
2545 mono_class_alloc_ext (klass);
2547 mono_image_lock (klass->image);
2549 if (klass->ext->properties) {
2550 /* We leak 'properties' which was allocated from the image mempool */
2551 mono_image_unlock (klass->image);
2555 klass->ext->property.first = first;
2556 klass->ext->property.count = count;
2558 /* Flush any pending writes as we do double checked locking on klass->ext->properties */
2559 mono_memory_barrier ();
2561 /* Leave this assignment as the last op in the function */
2562 klass->ext->properties = properties;
2564 mono_image_unlock (klass->image);
2568 inflate_method_listz (MonoMethod **methods, MonoClass *klass, MonoGenericContext *context)
2570 MonoMethod **om, **retval;
2573 for (om = methods, count = 0; *om; ++om, ++count)
2576 retval = g_new0 (MonoMethod*, count + 1);
2578 for (om = methods, count = 0; *om; ++om, ++count) {
2580 retval [count] = mono_class_inflate_generic_method_full_checked (*om, klass, context, &error);
2581 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2587 /*This method can fail the class.*/
2589 mono_class_setup_events (MonoClass *klass)
2592 guint startm, endm, i, j;
2593 guint32 cols [MONO_EVENT_SIZE];
2594 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2598 if (klass->ext && klass->ext->events)
2601 if (klass->generic_class) {
2602 MonoClass *gklass = klass->generic_class->container_class;
2603 MonoGenericContext *context = NULL;
2605 mono_class_setup_events (gklass);
2606 if (mono_class_has_failure (gklass)) {
2607 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2611 first = gklass->ext->event.first;
2612 count = gklass->ext->event.count;
2614 events = mono_class_new0 (klass, MonoEvent, count);
2617 context = mono_class_get_context (klass);
2619 for (i = 0; i < count; i++) {
2621 MonoEvent *event = &events [i];
2622 MonoEvent *gevent = &gklass->ext->events [i];
2624 mono_error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2626 event->parent = klass;
2627 event->name = gevent->name;
2628 event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, klass, context, &error) : NULL;
2629 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2630 event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, klass, context, &error) : NULL;
2631 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2632 event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, klass, context, &error) : NULL;
2633 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2635 #ifndef MONO_SMALL_CONFIG
2636 event->other = gevent->other ? inflate_method_listz (gevent->other, klass, context) : NULL;
2638 event->attrs = gevent->attrs;
2641 first = mono_metadata_events_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2642 count = last - first;
2645 mono_class_setup_methods (klass);
2646 if (mono_class_has_failure (klass)) {
2647 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2652 events = (MonoEvent *)mono_class_alloc0 (klass, sizeof (MonoEvent) * count);
2653 for (i = first; i < last; ++i) {
2654 MonoEvent *event = &events [i - first];
2656 mono_metadata_decode_table_row (klass->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2657 event->parent = klass;
2658 event->attrs = cols [MONO_EVENT_FLAGS];
2659 event->name = mono_metadata_string_heap (klass->image, cols [MONO_EVENT_NAME]);
2661 startm = mono_metadata_methods_from_event (klass->image, i, &endm);
2662 for (j = startm; j < endm; ++j) {
2665 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2667 if (klass->image->uncompressed_metadata) {
2669 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2670 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2671 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2673 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - klass->method.first];
2676 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2677 case METHOD_SEMANTIC_ADD_ON:
2678 event->add = method;
2680 case METHOD_SEMANTIC_REMOVE_ON:
2681 event->remove = method;
2683 case METHOD_SEMANTIC_FIRE:
2684 event->raise = method;
2686 case METHOD_SEMANTIC_OTHER: {
2687 #ifndef MONO_SMALL_CONFIG
2690 if (event->other == NULL) {
2691 event->other = g_new0 (MonoMethod*, 2);
2693 while (event->other [n])
2695 event->other = (MonoMethod **)g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2697 event->other [n] = method;
2698 /* NULL terminated */
2699 event->other [n + 1] = NULL;
2710 mono_class_alloc_ext (klass);
2712 mono_image_lock (klass->image);
2714 if (klass->ext->events) {
2715 mono_image_unlock (klass->image);
2719 klass->ext->event.first = first;
2720 klass->ext->event.count = count;
2722 /* Flush any pending writes as we do double checked locking on klass->ext.events */
2723 mono_memory_barrier ();
2725 /* Leave this assignment as the last op in the function */
2726 klass->ext->events = events;
2728 mono_image_unlock (klass->image);
2732 * Global pool of interface IDs, represented as a bitset.
2733 * LOCKING: Protected by the classes lock.
2735 static MonoBitSet *global_interface_bitset = NULL;
2738 * mono_unload_interface_ids:
2739 * @bitset: bit set of interface IDs
2741 * When an image is unloaded, the interface IDs associated with
2742 * the image are put back in the global pool of IDs so the numbers
2746 mono_unload_interface_ids (MonoBitSet *bitset)
2749 mono_bitset_sub (global_interface_bitset, bitset);
2754 mono_unload_interface_id (MonoClass *klass)
2756 if (global_interface_bitset && klass->interface_id) {
2758 mono_bitset_clear (global_interface_bitset, klass->interface_id);
2764 * mono_get_unique_iid:
2767 * Assign a unique integer ID to the interface represented by @class.
2768 * The ID will positive and as small as possible.
2769 * LOCKING: Acquires the classes lock.
2770 * Returns: The new ID.
2773 mono_get_unique_iid (MonoClass *klass)
2777 g_assert (MONO_CLASS_IS_INTERFACE (klass));
2781 if (!global_interface_bitset) {
2782 global_interface_bitset = mono_bitset_new (128, 0);
2785 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2787 int old_size = mono_bitset_size (global_interface_bitset);
2788 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2789 mono_bitset_free (global_interface_bitset);
2790 global_interface_bitset = new_set;
2793 mono_bitset_set (global_interface_bitset, iid);
2794 /* set the bit also in the per-image set */
2795 if (!klass->generic_class) {
2796 if (klass->image->interface_bitset) {
2797 if (iid >= mono_bitset_size (klass->image->interface_bitset)) {
2798 MonoBitSet *new_set = mono_bitset_clone (klass->image->interface_bitset, iid + 1);
2799 mono_bitset_free (klass->image->interface_bitset);
2800 klass->image->interface_bitset = new_set;
2803 klass->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2805 mono_bitset_set (klass->image->interface_bitset, iid);
2810 #ifndef MONO_SMALL_CONFIG
2811 if (mono_print_vtable) {
2813 char *type_name = mono_type_full_name (&klass->byval_arg);
2814 if (klass->generic_class && !klass->generic_class->context.class_inst->is_open) {
2815 generic_id = klass->generic_class->context.class_inst->id;
2816 g_assert (generic_id != 0);
2820 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, klass->image->name, type_name, generic_id);
2825 g_assert (iid <= 65535);
2830 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2835 mono_class_setup_interfaces (klass, error);
2836 return_if_nok (error);
2838 for (i = 0; i < klass->interface_count; i++) {
2839 ic = klass->interfaces [i];
2842 *res = g_ptr_array_new ();
2843 g_ptr_array_add (*res, ic);
2844 mono_class_init (ic);
2845 if (mono_class_has_failure (ic)) {
2846 mono_error_set_type_load_class (error, ic, "Error Loading class");
2850 collect_implemented_interfaces_aux (ic, res, error);
2851 return_if_nok (error);
2856 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2858 GPtrArray *res = NULL;
2860 collect_implemented_interfaces_aux (klass, &res, error);
2861 if (!mono_error_ok (error)) {
2863 g_ptr_array_free (res, TRUE);
2870 compare_interface_ids (const void *p_key, const void *p_element) {
2871 const MonoClass *key = (const MonoClass *)p_key;
2872 const MonoClass *element = *(const MonoClass **)p_element;
2874 return (key->interface_id - element->interface_id);
2877 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2879 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2880 MonoClass **result = (MonoClass **)mono_binary_search (
2882 klass->interfaces_packed,
2883 klass->interface_offsets_count,
2884 sizeof (MonoClass *),
2885 compare_interface_ids);
2887 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2894 * mono_class_interface_offset_with_variance:
2896 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2897 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2899 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2901 * FIXME figure out MS disambiguation rules and fix this function.
2904 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2905 int i = mono_class_interface_offset (klass, itf);
2906 *non_exact_match = FALSE;
2910 if (!mono_class_has_variant_generic_params (itf))
2913 for (i = 0; i < klass->interface_offsets_count; i++) {
2914 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2915 *non_exact_match = TRUE;
2916 return klass->interface_offsets_packed [i];
2924 print_implemented_interfaces (MonoClass *klass) {
2927 GPtrArray *ifaces = NULL;
2929 int ancestor_level = 0;
2931 name = mono_type_get_full_name (klass);
2932 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2935 for (i = 0; i < klass->interface_offsets_count; i++)
2936 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2937 klass->interfaces_packed [i]->interface_id,
2938 klass->interface_offsets_packed [i],
2939 klass->interfaces_packed [i]->method.count,
2940 klass->interfaces_packed [i]->name_space,
2941 klass->interfaces_packed [i]->name );
2942 printf ("Interface flags: ");
2943 for (i = 0; i <= klass->max_interface_id; i++)
2944 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2945 printf ("(%d,T)", i);
2947 printf ("(%d,F)", i);
2949 printf ("Dump interface flags:");
2950 #ifdef COMPRESSED_INTERFACE_BITMAP
2952 const uint8_t* p = klass->interface_bitmap;
2953 i = klass->max_interface_id;
2955 printf (" %d x 00 %02X", p [0], p [1]);
2961 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
2962 printf (" %02X", klass->interface_bitmap [i]);
2965 while (klass != NULL) {
2966 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
2967 ifaces = mono_class_get_implemented_interfaces (klass, &error);
2968 if (!mono_error_ok (&error)) {
2969 printf (" Type failed due to %s\n", mono_error_get_message (&error));
2970 mono_error_cleanup (&error);
2971 } else if (ifaces) {
2972 for (i = 0; i < ifaces->len; i++) {
2973 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
2974 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
2975 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2977 mono_class_interface_offset (klass, ic),
2982 g_ptr_array_free (ifaces, TRUE);
2985 klass = klass->parent;
2990 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
2993 args [0] = &arg0->byval_arg;
2995 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
2999 array_class_get_if_rank (MonoClass *klass, guint rank)
3001 return rank ? mono_array_class_get (klass, rank) : klass;
3005 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
3007 valuetype_types [0] = eclass;
3008 if (eclass == mono_defaults.int16_class)
3009 valuetype_types [1] = mono_defaults.uint16_class;
3010 else if (eclass == mono_defaults.uint16_class)
3011 valuetype_types [1] = mono_defaults.int16_class;
3012 else if (eclass == mono_defaults.int32_class)
3013 valuetype_types [1] = mono_defaults.uint32_class;
3014 else if (eclass == mono_defaults.uint32_class)
3015 valuetype_types [1] = mono_defaults.int32_class;
3016 else if (eclass == mono_defaults.int64_class)
3017 valuetype_types [1] = mono_defaults.uint64_class;
3018 else if (eclass == mono_defaults.uint64_class)
3019 valuetype_types [1] = mono_defaults.int64_class;
3020 else if (eclass == mono_defaults.byte_class)
3021 valuetype_types [1] = mono_defaults.sbyte_class;
3022 else if (eclass == mono_defaults.sbyte_class)
3023 valuetype_types [1] = mono_defaults.byte_class;
3024 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
3025 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
3028 /* this won't be needed once bug #325495 is completely fixed
3029 * though we'll need something similar to know which interfaces to allow
3030 * in arrays when they'll be lazyly created
3032 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
3033 * MS returns diferrent types based on which instance is called. For example:
3034 * object obj = new byte[10][];
3035 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
3036 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
3039 * Fixing this should kill quite some code, save some bits and improve compatibility.
3042 get_implicit_generic_array_interfaces (MonoClass *klass, int *num, int *is_enumerator)
3044 MonoClass *eclass = klass->element_class;
3045 static MonoClass* generic_icollection_class = NULL;
3046 static MonoClass* generic_ienumerable_class = NULL;
3047 static MonoClass* generic_ienumerator_class = NULL;
3048 static MonoClass* generic_ireadonlylist_class = NULL;
3049 static MonoClass* generic_ireadonlycollection_class = NULL;
3050 MonoClass *valuetype_types[2] = { NULL, NULL };
3051 MonoClass **interfaces = NULL;
3052 int i, nifaces, interface_count, real_count, original_rank;
3054 gboolean internal_enumerator;
3055 gboolean eclass_is_valuetype;
3057 if (!mono_defaults.generic_ilist_class) {
3061 internal_enumerator = FALSE;
3062 eclass_is_valuetype = FALSE;
3063 original_rank = eclass->rank;
3064 if (klass->byval_arg.type != MONO_TYPE_SZARRAY) {
3065 if (klass->generic_class && klass->nested_in == mono_defaults.array_class && strcmp (klass->name, "InternalEnumerator`1") == 0) {
3067 * For a Enumerator<T[]> we need to get the list of interfaces for T.
3069 eclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
3070 original_rank = eclass->rank;
3072 eclass = eclass->element_class;
3073 internal_enumerator = TRUE;
3074 *is_enumerator = TRUE;
3082 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
3083 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
3085 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
3087 if (!generic_icollection_class) {
3088 generic_icollection_class = mono_class_load_from_name (mono_defaults.corlib,
3089 "System.Collections.Generic", "ICollection`1");
3090 generic_ienumerable_class = mono_class_load_from_name (mono_defaults.corlib,
3091 "System.Collections.Generic", "IEnumerable`1");
3092 generic_ienumerator_class = mono_class_load_from_name (mono_defaults.corlib,
3093 "System.Collections.Generic", "IEnumerator`1");
3094 generic_ireadonlylist_class = mono_class_load_from_name (mono_defaults.corlib,
3095 "System.Collections.Generic", "IReadOnlyList`1");
3096 generic_ireadonlycollection_class = mono_class_load_from_name (mono_defaults.corlib,
3097 "System.Collections.Generic", "IReadOnlyCollection`1");
3100 mono_class_init (eclass);
3103 * Arrays in 2.0 need to implement a number of generic interfaces
3104 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
3105 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
3106 * We collect the types needed to build the
3107 * instantiations in interfaces at intervals of 3/5, because 3/5 are
3108 * the generic interfaces needed to implement.
3110 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
3111 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
3113 if (eclass->valuetype) {
3114 nifaces = generic_ireadonlylist_class ? 5 : 3;
3115 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
3117 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
3118 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
3119 if (internal_enumerator) {
3121 if (valuetype_types [1])
3125 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3126 interfaces [0] = valuetype_types [0];
3127 if (valuetype_types [1])
3128 interfaces [nifaces] = valuetype_types [1];
3130 eclass_is_valuetype = TRUE;
3133 int idepth = eclass->idepth;
3134 if (!internal_enumerator)
3136 nifaces = generic_ireadonlylist_class ? 2 : 3;
3138 // FIXME: This doesn't seem to work/required for generic params
3139 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
3140 mono_class_setup_interface_offsets (eclass);
3142 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
3143 /* we add object for interfaces and the supertypes for the other
3144 * types. The last of the supertypes is the element class itself which we
3145 * already created the explicit interfaces for (so we include it for IEnumerator
3146 * and exclude it for arrays).
3148 if (MONO_CLASS_IS_INTERFACE (eclass))
3151 interface_count += idepth;
3152 if (eclass->rank && eclass->element_class->valuetype) {
3153 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3154 if (valuetype_types [1])
3157 /* IList, ICollection, IEnumerable, IReadOnlyList */
3158 interface_count *= nifaces;
3159 real_count = interface_count;
3160 if (internal_enumerator) {
3161 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3162 if (valuetype_types [1])
3165 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3166 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3167 interfaces [0] = mono_defaults.object_class;
3171 for (i = 0; i < idepth; i++) {
3172 mono_class_init (eclass->supertypes [i]);
3173 interfaces [j] = eclass->supertypes [i];
3177 if (all_interfaces) {
3178 for (i = 0; i < eclass->interface_offsets_count; i++) {
3179 interfaces [j] = eclass->interfaces_packed [i];
3183 for (i = 0; i < eclass->interface_count; i++) {
3184 interfaces [j] = eclass->interfaces [i];
3188 if (valuetype_types [1]) {
3189 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3194 /* instantiate the generic interfaces */
3195 for (i = 0; i < interface_count; i += nifaces) {
3196 MonoClass *iface = interfaces [i];
3198 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3199 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3201 if (eclass->valuetype) {
3202 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3203 if (generic_ireadonlylist_class) {
3204 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3205 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3208 if (!generic_ireadonlylist_class)
3209 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3212 if (internal_enumerator) {
3214 /* instantiate IEnumerator<iface> */
3215 for (i = 0; i < interface_count; i++) {
3216 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3218 j = interface_count;
3219 if (!eclass_is_valuetype) {
3220 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3221 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3224 for (i = 0; i < eclass->idepth; i++) {
3225 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3229 for (i = 0; i < eclass->interface_offsets_count; i++) {
3230 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3234 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3236 if (valuetype_types [1])
3237 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3241 char *type_name = mono_type_get_name_full (&klass->byval_arg, 0);
3242 for (i = 0; i < real_count; ++i) {
3243 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3244 g_print ("%s implements %s\n", type_name, name);
3255 find_array_interface (MonoClass *klass, const char *name)
3258 for (i = 0; i < klass->interface_count; ++i) {
3259 if (strcmp (klass->interfaces [i]->name, name) == 0)
3266 * Return the number of virtual methods.
3267 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3268 * Return -1 on failure.
3269 * FIXME It would be nice if this information could be cached somewhere.
3272 count_virtual_methods (MonoClass *klass)
3276 klass = mono_class_get_generic_type_definition (klass); /*We can find this information by looking at the GTD*/
3278 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
3279 mono_class_setup_methods (klass);
3280 if (mono_class_has_failure (klass))
3283 for (i = 0; i < klass->method.count; ++i) {
3284 flags = klass->methods [i]->flags;
3285 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3289 for (i = 0; i < klass->method.count; ++i) {
3290 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
3292 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3300 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3308 m = (l + num_ifaces) / 2;
3309 if (interfaces_full [m] == ic)
3311 if (l == num_ifaces)
3313 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3322 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3324 int i = find_interface (num_ifaces, interfaces_full, ic);
3326 return interface_offsets_full [i];
3331 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3333 int i = find_interface (num_ifaces, interfaces_full, ic);
3337 interface_offsets_full [i] = offset;
3340 for (i = 0; i < num_ifaces; ++i) {
3341 if (interfaces_full [i]) {
3343 if (interfaces_full [i]->interface_id < ic->interface_id)
3346 while (end < num_ifaces && interfaces_full [end]) end++;
3347 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3348 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3350 interfaces_full [i] = ic;
3351 interface_offsets_full [i] = offset;
3357 #ifdef COMPRESSED_INTERFACE_BITMAP
3360 * Compressed interface bitmap design.
3362 * Interface bitmaps take a large amount of memory, because their size is
3363 * linear with the maximum interface id assigned in the process (each interface
3364 * is assigned a unique id as it is loaded). The number of interface classes
3365 * is high because of the many implicit interfaces implemented by arrays (we'll
3366 * need to lazy-load them in the future).
3367 * Most classes implement a very small number of interfaces, so the bitmap is
3368 * sparse. This bitmap needs to be checked by interface casts, so access to the
3369 * needed bit must be fast and doable with few jit instructions.
3371 * The current compression format is as follows:
3372 * *) it is a sequence of one or more two-byte elements
3373 * *) the first byte in the element is the count of empty bitmap bytes
3374 * at the current bitmap position
3375 * *) the second byte in the element is an actual bitmap byte at the current
3378 * As an example, the following compressed bitmap bytes:
3379 * 0x07 0x01 0x00 0x7
3380 * correspond to the following bitmap:
3381 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3383 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3384 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3385 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3389 * mono_compress_bitmap:
3390 * @dest: destination buffer
3391 * @bitmap: bitmap buffer
3392 * @size: size of @bitmap in bytes
3394 * This is a mono internal function.
3395 * The @bitmap data is compressed into a format that is small but
3396 * still searchable in few instructions by the JIT and runtime.
3397 * The compressed data is stored in the buffer pointed to by the
3398 * @dest array. Passing a #NULL value for @dest allows to just compute
3399 * the size of the buffer.
3400 * This compression algorithm assumes the bits set in the bitmap are
3401 * few and far between, like in interface bitmaps.
3402 * Returns: The size of the compressed bitmap in bytes.
3405 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3409 const uint8_t *end = bitmap + size;
3410 while (bitmap < end) {
3411 if (*bitmap || numz == 255) {
3435 * mono_class_interface_match:
3436 * @bitmap: a compressed bitmap buffer
3437 * @id: the index to check in the bitmap
3439 * This is a mono internal function.
3440 * Checks if a bit is set in a compressed interface bitmap. @id must
3441 * be already checked for being smaller than the maximum id encoded in the
3444 * Returns: A non-zero value if bit @id is set in the bitmap @bitmap,
3448 mono_class_interface_match (const uint8_t *bitmap, int id)
3451 id -= bitmap [0] * 8;
3455 return bitmap [1] & (1 << id);
3464 * LOCKING: this is supposed to be called with the loader lock held.
3465 * Return -1 on failure and set exception_type
3468 setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite)
3472 int i, j, max_iid, num_ifaces;
3473 MonoClass **interfaces_full = NULL;
3474 int *interface_offsets_full = NULL;
3476 GPtrArray **ifaces_array = NULL;
3477 int interface_offsets_count;
3478 MonoClass **array_interfaces = NULL;
3479 int num_array_interfaces;
3480 int is_enumerator = FALSE;
3482 mono_class_setup_supertypes (klass);
3484 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3485 * implicit interfaces have the property that they are assigned the same slot in the
3486 * vtables for compatible interfaces
3488 array_interfaces = get_implicit_generic_array_interfaces (klass, &num_array_interfaces, &is_enumerator);
3490 /* compute maximum number of slots and maximum interface id */
3492 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3493 ifaces_array = g_new0 (GPtrArray *, klass->idepth);
3494 for (j = 0; j < klass->idepth; j++) {
3495 k = klass->supertypes [j];
3496 num_ifaces += k->interface_count;
3497 for (i = 0; i < k->interface_count; i++) {
3498 ic = k->interfaces [i];
3501 mono_class_init (ic);
3503 if (max_iid < ic->interface_id)
3504 max_iid = ic->interface_id;
3506 ifaces = mono_class_get_implemented_interfaces (k, &error);
3507 if (!mono_error_ok (&error)) {
3508 char *name = mono_type_get_full_name (k);
3509 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error getting the interfaces of %s due to %s", name, mono_error_get_message (&error)));
3511 mono_error_cleanup (&error);
3516 num_ifaces += ifaces->len;
3517 for (i = 0; i < ifaces->len; ++i) {
3518 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3519 if (max_iid < ic->interface_id)
3520 max_iid = ic->interface_id;
3522 ifaces_array [j] = ifaces;
3526 for (i = 0; i < num_array_interfaces; ++i) {
3527 ic = array_interfaces [i];
3528 mono_class_init (ic);
3529 if (max_iid < ic->interface_id)
3530 max_iid = ic->interface_id;
3533 if (MONO_CLASS_IS_INTERFACE (klass)) {
3535 if (max_iid < klass->interface_id)
3536 max_iid = klass->interface_id;
3538 klass->max_interface_id = max_iid;
3539 /* compute vtable offset for interfaces */
3540 interfaces_full = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3541 interface_offsets_full = (int *)g_malloc (sizeof (int) * num_ifaces);
3543 for (i = 0; i < num_ifaces; i++) {
3544 interface_offsets_full [i] = -1;
3547 /* skip the current class */
3548 for (j = 0; j < klass->idepth - 1; j++) {
3549 k = klass->supertypes [j];
3550 ifaces = ifaces_array [j];
3553 for (i = 0; i < ifaces->len; ++i) {
3555 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3557 /*Force the sharing of interface offsets between parent and subtypes.*/
3558 io = mono_class_interface_offset (k, ic);
3560 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3565 g_assert (klass == klass->supertypes [klass->idepth - 1]);
3566 ifaces = ifaces_array [klass->idepth - 1];
3568 for (i = 0; i < ifaces->len; ++i) {
3570 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3571 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3573 count = count_virtual_methods (ic);
3575 char *name = mono_type_get_full_name (ic);
3576 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error calculating interface offset of %s", name));
3585 if (MONO_CLASS_IS_INTERFACE (klass))
3586 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, klass, cur_slot, TRUE);
3588 if (num_array_interfaces) {
3589 if (is_enumerator) {
3590 int ienumerator_idx = find_array_interface (klass, "IEnumerator`1");
3591 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ienumerator_idx]);
3592 g_assert (ienumerator_offset >= 0);
3593 for (i = 0; i < num_array_interfaces; ++i) {
3594 ic = array_interfaces [i];
3595 if (strcmp (ic->name, "IEnumerator`1") == 0)
3596 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3598 g_assert_not_reached ();
3599 /*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);*/
3602 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3603 int ilist_iface_idx = find_array_interface (klass, "IList`1");
3604 MonoClass* ilist_class = klass->interfaces [ilist_iface_idx];
3605 int ireadonlylist_iface_idx = find_array_interface (klass, "IReadOnlyList`1");
3606 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? klass->interfaces [ireadonlylist_iface_idx] : NULL;
3607 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3608 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3609 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3610 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ilist_iface_idx]);
3611 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3612 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3613 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ireadonlylist_iface_idx]) : -1;
3614 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3615 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3616 for (i = 0; i < num_array_interfaces; ++i) {
3618 ic = array_interfaces [i];
3619 if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
3620 offset = ilist_offset;
3621 else if (strcmp (ic->name, "ICollection`1") == 0)
3622 offset = icollection_offset;
3623 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3624 offset = ienumerable_offset;
3625 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3626 offset = ireadonlylist_offset;
3627 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3628 offset = ireadonlycollection_offset;
3630 g_assert_not_reached ();
3631 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3632 /*g_print ("type %s has %s offset at %d (%s)\n", klass->name, ic->name, offset, klass->interfaces [0]->name);*/
3637 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3638 if (interface_offsets_full [i] != -1) {
3639 interface_offsets_count ++;
3644 * We might get called multiple times:
3645 * - mono_class_init ()
3646 * - mono_class_setup_vtable ().
3647 * - mono_class_setup_interface_offsets ().
3648 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3649 * means we have to overwrite those when called from other places (#4440).
3651 if (klass->interfaces_packed) {
3653 g_assert (klass->interface_offsets_count == interface_offsets_count);
3657 klass->interface_offsets_count = interface_offsets_count;
3658 klass->interfaces_packed = (MonoClass **)mono_class_alloc (klass, sizeof (MonoClass*) * interface_offsets_count);
3659 klass->interface_offsets_packed = (guint16 *)mono_class_alloc (klass, sizeof (guint16) * interface_offsets_count);
3660 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3661 #ifdef COMPRESSED_INTERFACE_BITMAP
3662 bitmap = g_malloc0 (bsize);
3664 bitmap = (uint8_t *)mono_class_alloc0 (klass, bsize);
3666 for (i = 0; i < interface_offsets_count; i++) {
3667 int id = interfaces_full [i]->interface_id;
3668 bitmap [id >> 3] |= (1 << (id & 7));
3669 klass->interfaces_packed [i] = interfaces_full [i];
3670 klass->interface_offsets_packed [i] = interface_offsets_full [i];
3671 /*if (num_array_interfaces)
3672 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]);*/
3674 #ifdef COMPRESSED_INTERFACE_BITMAP
3675 i = mono_compress_bitmap (NULL, bitmap, bsize);
3676 klass->interface_bitmap = mono_class_alloc0 (klass, i);
3677 mono_compress_bitmap (klass->interface_bitmap, bitmap, bsize);
3680 klass->interface_bitmap = bitmap;
3685 g_free (interfaces_full);
3686 g_free (interface_offsets_full);
3687 g_free (array_interfaces);
3688 for (i = 0; i < klass->idepth; i++) {
3689 ifaces = ifaces_array [i];
3691 g_ptr_array_free (ifaces, TRUE);
3693 g_free (ifaces_array);
3695 //printf ("JUST DONE: ");
3696 //print_implemented_interfaces (klass);
3702 * Setup interface offsets for interfaces.
3704 * - klass->max_interface_id
3705 * - klass->interface_offsets_count
3706 * - klass->interfaces_packed
3707 * - klass->interface_offsets_packed
3708 * - klass->interface_bitmap
3710 * This function can fail @class.
3713 mono_class_setup_interface_offsets (MonoClass *klass)
3715 mono_loader_lock ();
3717 setup_interface_offsets (klass, 0, FALSE);
3719 mono_loader_unlock ();
3722 /*Checks if @klass has @parent as one of it's parents type gtd
3726 * Bar<T> : Foo<Bar<Bar<T>>>
3730 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3732 klass = mono_class_get_generic_type_definition (klass);
3733 parent = mono_class_get_generic_type_definition (parent);
3734 mono_class_setup_supertypes (klass);
3735 mono_class_setup_supertypes (parent);
3737 return klass->idepth >= parent->idepth &&
3738 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3742 mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup)
3744 MonoGenericInst *ginst;
3746 if (!klass->generic_class) {
3747 mono_class_setup_vtable_full (klass, in_setup);
3748 return !mono_class_has_failure (klass);
3751 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup);
3752 if (mono_class_has_failure (klass->generic_class->container_class)) {
3753 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to load generic definition vtable"));
3757 ginst = klass->generic_class->context.class_inst;
3758 for (i = 0; i < ginst->type_argc; ++i) {
3760 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3762 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3763 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3764 if (mono_class_has_gtd_parent (klass, arg) || mono_class_has_gtd_parent (arg, klass))
3766 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3767 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Failed to load generic parameter %d", i));
3775 * mono_class_setup_vtable:
3777 * Creates the generic vtable of CLASS.
3778 * Initializes the following fields in MonoClass:
3781 * Plus all the fields initialized by setup_interface_offsets ().
3782 * If there is an error during vtable construction, klass->exception_type is set.
3784 * LOCKING: Acquires the loader lock.
3787 mono_class_setup_vtable (MonoClass *klass)
3789 mono_class_setup_vtable_full (klass, NULL);
3793 mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
3796 MonoMethod **overrides;
3797 MonoGenericContext *context;
3805 if (MONO_CLASS_IS_INTERFACE (klass)) {
3806 /* This sets method->slot for all methods if this is an interface */
3807 mono_class_setup_methods (klass);
3811 if (mono_class_has_failure (klass))
3814 if (g_list_find (in_setup, klass))
3817 mono_loader_lock ();
3819 if (klass->vtable) {
3820 mono_loader_unlock ();
3824 mono_stats.generic_vtable_count ++;
3825 in_setup = g_list_prepend (in_setup, klass);
3827 if (klass->generic_class) {
3828 if (!mono_class_check_vtable_constraints (klass, in_setup)) {
3829 mono_loader_unlock ();
3830 g_list_remove (in_setup, klass);
3834 context = mono_class_get_context (klass);
3835 type_token = klass->generic_class->container_class->type_token;
3837 context = (MonoGenericContext *) klass->generic_container;
3838 type_token = klass->type_token;
3841 if (image_is_dynamic (klass->image)) {
3842 /* Generic instances can have zero method overrides without causing any harm.
3843 * This is true since we don't do layout all over again for them, we simply inflate
3844 * the layout of the parent.
3846 mono_reflection_get_dynamic_overrides (klass, &overrides, &onum, &error);
3847 if (!is_ok (&error)) {
3848 mono_loader_unlock ();
3849 g_list_remove (in_setup, klass);
3850 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf("Could not load list of method overrides due to %s", mono_error_get_message (&error)));
3851 mono_error_cleanup (&error);
3855 /* The following call fails if there are missing methods in the type */
3856 /* FIXME it's probably a good idea to avoid this for generic instances. */
3857 ok = mono_class_get_overrides_full (klass->image, type_token, &overrides, &onum, context);
3861 mono_class_setup_vtable_general (klass, overrides, onum, in_setup);
3863 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load list of method overrides"));
3867 mono_loader_unlock ();
3868 g_list_remove (in_setup, klass);
3873 #define DEBUG_INTERFACE_VTABLE_CODE 0
3874 #define TRACE_INTERFACE_VTABLE_CODE 0
3875 #define VERIFY_INTERFACE_VTABLE_CODE 0
3876 #define VTABLE_SELECTOR (1)
3878 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3879 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3880 if (!(VTABLE_SELECTOR)) break; \
3884 #define DEBUG_INTERFACE_VTABLE(stmt)
3887 #if TRACE_INTERFACE_VTABLE_CODE
3888 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3889 if (!(VTABLE_SELECTOR)) break; \
3893 #define TRACE_INTERFACE_VTABLE(stmt)
3896 #if VERIFY_INTERFACE_VTABLE_CODE
3897 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3898 if (!(VTABLE_SELECTOR)) break; \
3902 #define VERIFY_INTERFACE_VTABLE(stmt)
3906 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3908 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3912 GString *res = g_string_new ("");
3914 g_string_append_c (res, '(');
3915 for (i = 0; i < sig->param_count; ++i) {
3917 g_string_append_c (res, ',');
3918 mono_type_get_desc (res, sig->params [i], include_namespace);
3920 g_string_append (res, ")=>");
3921 if (sig->ret != NULL) {
3922 mono_type_get_desc (res, sig->ret, include_namespace);
3924 g_string_append (res, "NULL");
3927 g_string_free (res, FALSE);
3931 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3932 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3933 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3934 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3942 is_wcf_hack_disabled (void)
3944 static gboolean disabled;
3945 static gboolean inited = FALSE;
3947 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3954 check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
3956 MonoMethodSignature *cmsig, *imsig;
3957 if (strcmp (im->name, cm->name) == 0) {
3958 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3959 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3962 if (! slot_is_empty) {
3963 if (require_newslot) {
3964 if (! interface_is_explicitly_implemented_by_class) {
3965 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3968 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3969 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3973 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3976 cmsig = mono_method_signature (cm);
3977 imsig = mono_method_signature (im);
3978 if (!cmsig || !imsig) {
3979 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3983 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3984 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3985 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3986 TRACE_INTERFACE_VTABLE (printf ("]"));
3989 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3990 if (mono_security_core_clr_enabled ())
3991 mono_security_core_clr_check_override (klass, cm, im);
3993 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
3994 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3995 char *body_name = mono_method_full_name (cm, TRUE);
3996 char *decl_name = mono_method_full_name (im, TRUE);
3997 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Method %s overrides method '%s' which is not accessible", body_name, decl_name));
4005 MonoClass *ic = im->klass;
4006 const char *ic_name_space = ic->name_space;
4007 const char *ic_name = ic->name;
4010 if (! require_newslot) {
4011 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
4014 if (cm->klass->rank == 0) {
4015 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
4018 cmsig = mono_method_signature (cm);
4019 imsig = mono_method_signature (im);
4020 if (!cmsig || !imsig) {
4021 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
4025 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4026 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
4027 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4028 TRACE_INTERFACE_VTABLE (printf ("]"));
4031 if (mono_class_get_image (ic) != mono_defaults.corlib) {
4032 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
4035 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
4036 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
4039 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))) {
4040 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
4044 subname = strstr (cm->name, ic_name_space);
4045 if (subname != cm->name) {
4046 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
4049 subname += strlen (ic_name_space);
4050 if (subname [0] != '.') {
4051 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
4055 if (strstr (subname, ic_name) != subname) {
4056 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
4059 subname += strlen (ic_name);
4060 if (subname [0] != '.') {
4061 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
4065 if (strcmp (subname, im->name) != 0) {
4066 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
4070 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
4071 if (mono_security_core_clr_enabled ())
4072 mono_security_core_clr_check_override (klass, cm, im);
4074 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
4075 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4076 char *body_name = mono_method_full_name (cm, TRUE);
4077 char *decl_name = mono_method_full_name (im, TRUE);
4078 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Method %s overrides method '%s' which is not accessible", body_name, decl_name));
4088 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
4090 foreach_override (gpointer key, gpointer value, gpointer user_data) {
4091 MonoMethod *method = key;
4092 MonoMethod *override = value;
4093 MonoClass *method_class = mono_method_get_class (method);
4094 MonoClass *override_class = mono_method_get_class (override);
4096 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
4097 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
4098 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
4101 print_overrides (GHashTable *override_map, const char *message) {
4103 printf ("Override map \"%s\" START:\n", message);
4104 g_hash_table_foreach (override_map, foreach_override, NULL);
4105 printf ("Override map \"%s\" END.\n", message);
4107 printf ("Override map \"%s\" EMPTY.\n", message);
4111 print_vtable_full (MonoClass *klass, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
4112 char *full_name = mono_type_full_name (&klass->byval_arg);
4116 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
4118 if (print_interfaces) {
4119 print_implemented_interfaces (klass);
4120 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
4123 if (klass->parent) {
4124 parent_size = klass->parent->vtable_size;
4128 for (i = 0; i < size; ++i) {
4129 MonoMethod *cm = vtable [i];
4130 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
4131 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
4133 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
4141 #if VERIFY_INTERFACE_VTABLE_CODE
4143 mono_method_try_get_vtable_index (MonoMethod *method)
4145 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4146 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4147 if (imethod->declaring->is_generic)
4148 return imethod->declaring->slot;
4150 return method->slot;
4154 mono_class_verify_vtable (MonoClass *klass)
4157 char *full_name = mono_type_full_name (&klass->byval_arg);
4159 printf ("*** Verifying VTable of class '%s' \n", full_name);
4163 if (!klass->methods)
4166 for (i = 0; i < klass->method.count; ++i) {
4167 MonoMethod *cm = klass->methods [i];
4170 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4174 full_name = mono_method_full_name (cm, TRUE);
4176 slot = mono_method_try_get_vtable_index (cm);
4178 if (slot >= klass->vtable_size) {
4179 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, klass->vtable_size);
4183 if (slot >= 0 && klass->vtable [slot] != cm && (klass->vtable [slot])) {
4184 char *other_name = klass->vtable [slot] ? mono_method_full_name (klass->vtable [slot], TRUE) : g_strdup ("[null value]");
4185 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4186 g_free (other_name);
4189 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4196 print_unimplemented_interface_method_info (MonoClass *klass, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4198 char *method_signature;
4201 for (index = 0; index < onum; ++index) {
4202 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4203 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4205 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4206 type_name = mono_type_full_name (&klass->byval_arg);
4207 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4208 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4209 g_free (method_signature);
4211 mono_class_setup_methods (klass);
4212 if (mono_class_has_failure (klass)) {
4213 char *name = mono_type_get_full_name (klass);
4214 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4218 for (index = 0; index < klass->method.count; ++index) {
4219 MonoMethod *cm = klass->methods [index];
4220 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4222 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4223 g_free (method_signature);
4228 mono_method_get_method_definition (MonoMethod *method)
4230 while (method->is_inflated)
4231 method = ((MonoMethodInflated*)method)->declaring;
4236 verify_class_overrides (MonoClass *klass, MonoMethod **overrides, int onum)
4240 for (i = 0; i < onum; ++i) {
4241 MonoMethod *decl = overrides [i * 2];
4242 MonoMethod *body = overrides [i * 2 + 1];
4244 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (klass)) {
4245 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method belongs to a different class than the declared one"));
4249 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4250 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4251 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must not be static to override a base type"));
4253 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must be virtual to override a base type"));
4257 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4258 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4259 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a static method in a base type"));
4261 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a non virtual method in a base type"));
4265 if (!mono_class_is_assignable_from_slow (decl->klass, klass)) {
4266 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method overrides a class or interface that is not extended or implemented by this type"));
4270 body = mono_method_get_method_definition (body);
4271 decl = mono_method_get_method_definition (decl);
4273 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4274 char *body_name = mono_method_full_name (body, TRUE);
4275 char *decl_name = mono_method_full_name (decl, TRUE);
4276 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Method %s overrides method '%s' which is not accessible", body_name, decl_name));
4286 mono_class_need_stelemref_method (MonoClass *klass)
4288 return klass->rank == 1 && MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg);
4292 * LOCKING: this is supposed to be called with the loader lock held.
4295 mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int onum, GList *in_setup)
4299 MonoMethod **vtable;
4300 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4301 GPtrArray *ifaces = NULL;
4302 GHashTable *override_map = NULL;
4304 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4305 int first_non_interface_slot;
4307 GSList *virt_methods = NULL, *l;
4308 int stelemref_slot = 0;
4313 if (overrides && !verify_class_overrides (klass, overrides, onum))
4316 ifaces = mono_class_get_implemented_interfaces (klass, &error);
4317 if (!mono_error_ok (&error)) {
4318 char *name = mono_type_get_full_name (klass);
4319 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Could not resolve %s interfaces due to %s", name, mono_error_get_message (&error)));
4321 mono_error_cleanup (&error);
4323 } else if (ifaces) {
4324 for (i = 0; i < ifaces->len; i++) {
4325 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
4326 max_vtsize += ic->method.count;
4328 g_ptr_array_free (ifaces, TRUE);
4332 if (klass->parent) {
4333 mono_class_init (klass->parent);
4334 mono_class_setup_vtable_full (klass->parent, in_setup);
4336 if (mono_class_has_failure (klass->parent)) {
4337 char *name = mono_type_get_full_name (klass->parent);
4338 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Parent %s failed to load", name));
4343 max_vtsize += klass->parent->vtable_size;
4344 cur_slot = klass->parent->vtable_size;
4347 max_vtsize += klass->method.count;
4349 /*Array have a slot for stelemref*/
4350 if (mono_class_need_stelemref_method (klass)) {
4351 stelemref_slot = cur_slot;
4356 vtable = (MonoMethod **)alloca (sizeof (gpointer) * max_vtsize);
4357 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4359 /* printf ("METAINIT %s.%s\n", klass->name_space, klass->name); */
4361 cur_slot = setup_interface_offsets (klass, cur_slot, TRUE);
4362 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4365 max_iid = klass->max_interface_id;
4366 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4368 /* Optimized version for generic instances */
4369 if (klass->generic_class) {
4371 MonoClass *gklass = klass->generic_class->container_class;
4374 mono_class_setup_vtable_full (gklass, in_setup);
4375 if (mono_class_has_failure (gklass)) {
4376 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
4380 tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * gklass->vtable_size);
4381 klass->vtable_size = gklass->vtable_size;
4382 for (i = 0; i < gklass->vtable_size; ++i)
4383 if (gklass->vtable [i]) {
4384 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], klass, mono_class_get_context (klass), &error);
4385 if (!mono_error_ok (&error)) {
4386 char *err_msg = g_strdup_printf ("Could not inflate method due to %s", mono_error_get_message (&error));
4387 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
4389 mono_error_cleanup (&error);
4393 tmp [i]->slot = gklass->vtable [i]->slot;
4395 mono_memory_barrier ();
4396 klass->vtable = tmp;
4398 /* Have to set method->slot for abstract virtual methods */
4399 if (klass->methods && gklass->methods) {
4400 for (i = 0; i < klass->method.count; ++i)
4401 if (klass->methods [i]->slot == -1)
4402 klass->methods [i]->slot = gklass->methods [i]->slot;
4408 if (klass->parent && klass->parent->vtable_size) {
4409 MonoClass *parent = klass->parent;
4412 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4414 // Also inherit parent interface vtables, just as a starting point.
4415 // This is needed otherwise bug-77127.exe fails when the property methods
4416 // have different names in the iterface and the class, because for child
4417 // classes the ".override" information is not used anymore.
4418 for (i = 0; i < parent->interface_offsets_count; i++) {
4419 MonoClass *parent_interface = parent->interfaces_packed [i];
4420 int interface_offset = mono_class_interface_offset (klass, parent_interface);
4421 /*FIXME this is now dead code as this condition will never hold true.
4422 Since interface offsets are inherited then the offset of an interface implemented
4423 by a parent will never be the out of it's vtable boundary.
4425 if (interface_offset >= parent->vtable_size) {
4426 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4429 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4430 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4431 for (j = 0; j < parent_interface->method.count && !mono_class_has_failure (klass); j++) {
4432 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4433 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4434 parent_interface_offset + j, parent_interface_offset, j,
4435 interface_offset + j, interface_offset, j));
4442 /*Array have a slot for stelemref*/
4443 if (mono_class_need_stelemref_method (klass)) {
4444 MonoMethod *method = mono_marshal_get_virtual_stelemref (klass);
4446 method->slot = stelemref_slot;
4448 g_assert (method->slot == stelemref_slot);
4450 vtable [stelemref_slot] = method;
4453 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4454 /* override interface methods */
4455 for (i = 0; i < onum; i++) {
4456 MonoMethod *decl = overrides [i*2];
4457 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4459 dslot = mono_method_get_vtable_slot (decl);
4461 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
4465 dslot += mono_class_interface_offset (klass, decl->klass);
4466 vtable [dslot] = overrides [i*2 + 1];
4467 vtable [dslot]->slot = dslot;
4469 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4471 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4473 if (mono_security_core_clr_enabled ())
4474 mono_security_core_clr_check_override (klass, vtable [dslot], decl);
4477 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4478 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4481 * Create a list of virtual methods to avoid calling
4482 * mono_class_get_virtual_methods () which is slow because of the metadata
4486 gpointer iter = NULL;
4489 virt_methods = NULL;
4490 while ((cm = mono_class_get_virtual_methods (klass, &iter))) {
4491 virt_methods = g_slist_prepend (virt_methods, cm);
4493 if (mono_class_has_failure (klass))
4497 // Loop on all implemented interfaces...
4498 for (i = 0; i < klass->interface_offsets_count; i++) {
4499 MonoClass *parent = klass->parent;
4501 gboolean interface_is_explicitly_implemented_by_class;
4504 ic = klass->interfaces_packed [i];
4505 ic_offset = mono_class_interface_offset (klass, ic);
4507 mono_class_setup_methods (ic);
4508 if (mono_class_has_failure (ic))
4511 // Check if this interface is explicitly implemented (instead of just inherited)
4512 if (parent != NULL) {
4513 int implemented_interfaces_index;
4514 interface_is_explicitly_implemented_by_class = FALSE;
4515 for (implemented_interfaces_index = 0; implemented_interfaces_index < klass->interface_count; implemented_interfaces_index++) {
4516 if (ic == klass->interfaces [implemented_interfaces_index]) {
4517 interface_is_explicitly_implemented_by_class = TRUE;
4522 interface_is_explicitly_implemented_by_class = TRUE;
4525 // Loop on all interface methods...
4526 for (im_index = 0; im_index < ic->method.count; im_index++) {
4527 MonoMethod *im = ic->methods [im_index];
4528 int im_slot = ic_offset + im->slot;
4529 MonoMethod *override_im = (override_map != NULL) ? (MonoMethod *)g_hash_table_lookup (override_map, im) : NULL;
4531 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4534 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4536 // If there is an explicit implementation, just use it right away,
4537 // otherwise look for a matching method
4538 if (override_im == NULL) {
4542 // First look for a suitable method among the class methods
4543 for (l = virt_methods; l; l = l->next) {
4544 cm = (MonoMethod *)l->data;
4545 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)));
4546 if (check_interface_method_override (klass, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
4547 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4548 vtable [im_slot] = cm;
4549 /* Why do we need this? */
4554 TRACE_INTERFACE_VTABLE (printf ("\n"));
4555 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4559 // If the slot is still empty, look in all the inherited virtual methods...
4560 if ((vtable [im_slot] == NULL) && klass->parent != NULL) {
4561 MonoClass *parent = klass->parent;
4562 // Reverse order, so that last added methods are preferred
4563 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4564 MonoMethod *cm = parent->vtable [cm_index];
4566 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));
4567 if ((cm != NULL) && check_interface_method_override (klass, im, cm, FALSE, FALSE, TRUE)) {
4568 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4569 vtable [im_slot] = cm;
4570 /* Why do we need this? */
4576 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4578 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4582 g_assert (vtable [im_slot] == override_im);
4587 // If the class is not abstract, check that all its interface slots are full.
4588 // The check is done here and not directly at the end of the loop above because
4589 // it can happen (for injected generic array interfaces) that the same slot is
4590 // processed multiple times (those interfaces have overlapping slots), and it
4591 // will not always be the first pass the one that fills the slot.
4592 if (! (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4593 for (i = 0; i < klass->interface_offsets_count; i++) {
4597 ic = klass->interfaces_packed [i];
4598 ic_offset = mono_class_interface_offset (klass, ic);
4600 for (im_index = 0; im_index < ic->method.count; im_index++) {
4601 MonoMethod *im = ic->methods [im_index];
4602 int im_slot = ic_offset + im->slot;
4604 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4607 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4608 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4609 if (vtable [im_slot] == NULL) {
4610 print_unimplemented_interface_method_info (klass, ic, im, im_slot, overrides, onum);
4617 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4618 for (l = virt_methods; l; l = l->next) {
4619 cm = (MonoMethod *)l->data;
4621 * If the method is REUSE_SLOT, we must check in the
4622 * base class for a method to override.
4624 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4626 for (k = klass->parent; k ; k = k->parent) {
4631 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4632 MonoMethodSignature *cmsig, *m1sig;
4634 cmsig = mono_method_signature (cm);
4635 m1sig = mono_method_signature (m1);
4637 if (!cmsig || !m1sig) {
4638 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
4642 if (!strcmp(cm->name, m1->name) &&
4643 mono_metadata_signature_equal (cmsig, m1sig)) {
4645 if (mono_security_core_clr_enabled ())
4646 mono_security_core_clr_check_override (klass, cm, m1);
4648 slot = mono_method_get_vtable_slot (m1);
4652 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4653 char *body_name = mono_method_full_name (cm, TRUE);
4654 char *decl_name = mono_method_full_name (m1, TRUE);
4655 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Method %s overrides method '%s' which is not accessible", body_name, decl_name));
4661 g_assert (cm->slot < max_vtsize);
4663 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4664 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4665 mono_method_full_name (m1, 1), m1,
4666 mono_method_full_name (cm, 1), cm));
4667 g_hash_table_insert (override_map, m1, cm);
4671 if (mono_class_has_failure (k))
4681 /*Non final newslot methods must be given a non-interface vtable slot*/
4682 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4686 cm->slot = cur_slot++;
4688 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4689 vtable [cm->slot] = cm;
4692 /* override non interface methods */
4693 for (i = 0; i < onum; i++) {
4694 MonoMethod *decl = overrides [i*2];
4695 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4696 g_assert (decl->slot != -1);
4697 vtable [decl->slot] = overrides [i*2 + 1];
4698 overrides [i * 2 + 1]->slot = decl->slot;
4700 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4701 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4702 mono_method_full_name (decl, 1), decl,
4703 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4704 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4706 if (mono_security_core_clr_enabled ())
4707 mono_security_core_clr_check_override (klass, vtable [decl->slot], decl);
4712 * If a method occupies more than one place in the vtable, and it is
4713 * overriden, then change the other occurances too.
4718 for (i = 0; i < max_vtsize; ++i)
4720 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4722 cm = (MonoMethod *)g_hash_table_lookup (override_map, vtable [i]);
4727 g_hash_table_destroy (override_map);
4728 override_map = NULL;
4731 g_slist_free (virt_methods);
4732 virt_methods = NULL;
4734 /* Ensure that all vtable slots are filled with concrete instance methods */
4735 if (!(klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4736 for (i = 0; i < cur_slot; ++i) {
4737 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4738 char *type_name = mono_type_get_full_name (klass);
4739 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4740 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name));
4742 g_free (method_name);
4748 if (klass->generic_class) {
4749 MonoClass *gklass = klass->generic_class->container_class;
4751 mono_class_init (gklass);
4753 klass->vtable_size = MAX (gklass->vtable_size, cur_slot);
4755 /* Check that the vtable_size value computed in mono_class_init () is correct */
4756 if (klass->vtable_size)
4757 g_assert (cur_slot == klass->vtable_size);
4758 klass->vtable_size = cur_slot;
4761 /* Try to share the vtable with our parent. */
4762 if (klass->parent && (klass->parent->vtable_size == klass->vtable_size) && (memcmp (klass->parent->vtable, vtable, sizeof (gpointer) * klass->vtable_size) == 0)) {
4763 mono_memory_barrier ();
4764 klass->vtable = klass->parent->vtable;
4766 MonoMethod **tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * klass->vtable_size);
4767 memcpy (tmp, vtable, sizeof (gpointer) * klass->vtable_size);
4768 mono_memory_barrier ();
4769 klass->vtable = tmp;
4772 DEBUG_INTERFACE_VTABLE (print_vtable_full (klass, klass->vtable, klass->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4773 if (mono_print_vtable) {
4776 print_implemented_interfaces (klass);
4778 for (i = 0; i <= max_iid; i++)
4779 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
4782 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&klass->byval_arg),
4783 klass->vtable_size, icount);
4785 for (i = 0; i < cur_slot; ++i) {
4790 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4791 mono_method_full_name (cm, TRUE));
4797 printf ("Interfaces %s.%s (max_iid = %d)\n", klass->name_space,
4798 klass->name, max_iid);
4800 for (i = 0; i < klass->interface_count; i++) {
4801 ic = klass->interfaces [i];
4802 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4803 mono_class_interface_offset (klass, ic),
4804 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4807 for (k = klass->parent; k ; k = k->parent) {
4808 for (i = 0; i < k->interface_count; i++) {
4809 ic = k->interfaces [i];
4810 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4811 mono_class_interface_offset (klass, ic),
4812 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4818 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (klass));
4823 char *name = mono_type_get_full_name (klass);
4824 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("VTable setup of type %s failed", name));
4827 g_hash_table_destroy (override_map);
4829 g_slist_free (virt_methods);
4834 * mono_method_get_vtable_slot:
4836 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4837 * LOCKING: Acquires the loader lock.
4839 * FIXME Use proper MonoError machinery here.
4842 mono_method_get_vtable_slot (MonoMethod *method)
4844 if (method->slot == -1) {
4845 mono_class_setup_vtable (method->klass);
4846 if (mono_class_has_failure (method->klass))
4848 if (method->slot == -1) {
4852 if (!method->klass->generic_class) {
4853 g_assert (method->is_inflated);
4854 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4857 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4858 g_assert (method->klass->generic_class);
4859 gklass = method->klass->generic_class->container_class;
4860 mono_class_setup_methods (method->klass);
4861 g_assert (method->klass->methods);
4862 for (i = 0; i < method->klass->method.count; ++i) {
4863 if (method->klass->methods [i] == method)
4866 g_assert (i < method->klass->method.count);
4867 g_assert (gklass->methods);
4868 method->slot = gklass->methods [i]->slot;
4870 g_assert (method->slot != -1);
4872 return method->slot;
4876 * mono_method_get_vtable_index:
4879 * Returns the index into the runtime vtable to access the method or,
4880 * in the case of a virtual generic method, the virtual generic method
4881 * thunk. Returns -1 on failure.
4883 * FIXME Use proper MonoError machinery here.
4886 mono_method_get_vtable_index (MonoMethod *method)
4888 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4889 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4890 if (imethod->declaring->is_generic)
4891 return mono_method_get_vtable_slot (imethod->declaring);
4893 return mono_method_get_vtable_slot (method);
4896 static MonoMethod *default_ghc = NULL;
4897 static MonoMethod *default_finalize = NULL;
4898 static int finalize_slot = -1;
4899 static int ghc_slot = -1;
4902 initialize_object_slots (MonoClass *klass)
4907 if (klass == mono_defaults.object_class) {
4908 mono_class_setup_vtable (klass);
4909 for (i = 0; i < klass->vtable_size; ++i) {
4910 MonoMethod *cm = klass->vtable [i];
4912 if (!strcmp (cm->name, "GetHashCode"))
4914 else if (!strcmp (cm->name, "Finalize"))
4918 g_assert (ghc_slot > 0);
4919 default_ghc = klass->vtable [ghc_slot];
4921 g_assert (finalize_slot > 0);
4922 default_finalize = klass->vtable [finalize_slot];
4927 MonoMethod *array_method;
4929 } GenericArrayMethodInfo;
4931 static int generic_array_method_num = 0;
4932 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4935 generic_array_methods (MonoClass *klass)
4937 int i, count_generic = 0;
4938 GList *list = NULL, *tmp;
4939 if (generic_array_method_num)
4940 return generic_array_method_num;
4941 mono_class_setup_methods (klass->parent); /*This is setting up System.Array*/
4942 g_assert (!mono_class_has_failure (klass->parent)); /*So hitting this assert is a huge problem*/
4943 for (i = 0; i < klass->parent->method.count; i++) {
4944 MonoMethod *m = klass->parent->methods [i];
4945 if (!strncmp (m->name, "InternalArray__", 15)) {
4947 list = g_list_prepend (list, m);
4950 list = g_list_reverse (list);
4951 generic_array_method_info = (GenericArrayMethodInfo *)mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4953 for (tmp = list; tmp; tmp = tmp->next) {
4954 const char *mname, *iname;
4956 MonoMethod *m = (MonoMethod *)tmp->data;
4957 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4958 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4960 generic_array_method_info [i].array_method = m;
4961 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4962 iname = "System.Collections.Generic.ICollection`1.";
4963 mname = m->name + 27;
4964 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4965 iname = "System.Collections.Generic.IEnumerable`1.";
4966 mname = m->name + 27;
4967 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4968 iname = "System.Collections.Generic.IReadOnlyList`1.";
4969 mname = m->name + strlen (ireadonlylist_prefix);
4970 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4971 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4972 mname = m->name + strlen (ireadonlycollection_prefix);
4973 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4974 iname = "System.Collections.Generic.IList`1.";
4975 mname = m->name + 15;
4977 g_assert_not_reached ();
4980 name = (gchar *)mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4981 strcpy (name, iname);
4982 strcpy (name + strlen (iname), mname);
4983 generic_array_method_info [i].name = name;
4986 /*g_print ("array generic methods: %d\n", count_generic);*/
4988 generic_array_method_num = count_generic;
4990 return generic_array_method_num;
4994 setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos)
4996 MonoGenericContext tmp_context;
4999 tmp_context.class_inst = NULL;
5000 tmp_context.method_inst = iface->generic_class->context.class_inst;
5001 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
5003 for (i = 0; i < generic_array_method_num; i++) {
5005 MonoMethod *m = generic_array_method_info [i].array_method;
5006 MonoMethod *inflated;
5008 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
5009 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
5010 methods [pos++] = mono_marshal_get_generic_array_helper (klass, iface, generic_array_method_info [i].name, inflated);
5015 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
5017 int null_length = strlen ("(null)");
5018 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
5019 char *s = (char *)mono_image_alloc (image, len);
5022 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
5023 g_assert (result == len - 1);
5029 set_failure_from_loader_error (MonoClass *klass, MonoLoaderError *error)
5031 gpointer exception_data = NULL;
5033 switch (error->exception_type) {
5034 case MONO_EXCEPTION_TYPE_LOAD:
5035 exception_data = concat_two_strings_with_zero (klass->image, error->class_name, error->assembly_name);
5038 case MONO_EXCEPTION_MISSING_METHOD:
5039 exception_data = concat_two_strings_with_zero (klass->image, error->class_name, error->member_name);
5042 case MONO_EXCEPTION_MISSING_FIELD: {
5043 const char *name_space = error->klass->name_space ? error->klass->name_space : NULL;
5044 const char *class_name;
5047 class_name = g_strdup_printf ("%s.%s", name_space, error->klass->name);
5049 class_name = error->klass->name;
5051 exception_data = concat_two_strings_with_zero (klass->image, class_name, error->member_name);
5054 g_free ((void*)class_name);
5058 case MONO_EXCEPTION_FILE_NOT_FOUND: {
5061 if (error->ref_only)
5062 msg = "Cannot resolve dependency to assembly '%s' because it has not been preloaded. When using the ReflectionOnly APIs, dependent assemblies must be pre-loaded or loaded on demand through the ReflectionOnlyAssemblyResolve event.";
5064 msg = "Could not load file or assembly '%s' or one of its dependencies.";
5066 exception_data = concat_two_strings_with_zero (klass->image, msg, error->assembly_name);
5070 case MONO_EXCEPTION_BAD_IMAGE:
5071 exception_data = error->msg;
5075 g_assert_not_reached ();
5078 mono_class_set_failure (klass, error->exception_type, exception_data);
5083 * @class: the class to initialize
5085 * Compute the instance_size, class_size and other infos that cannot be
5086 * computed at mono_class_get() time. Also compute vtable_size if possible.
5087 * Returns TRUE on success or FALSE if there was a problem in loading
5088 * the type (incorrect assemblies, missing assemblies, methods, etc).
5090 * LOCKING: Acquires the loader lock.
5093 mono_class_init (MonoClass *klass)
5096 MonoCachedClassInfo cached_info;
5097 gboolean has_cached_info;
5101 /* Double-checking locking pattern */
5102 if (klass->inited || mono_class_has_failure (klass))
5103 return !mono_class_has_failure (klass);
5105 /*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/
5107 /* We do everything inside the lock to prevent races */
5108 mono_loader_lock ();
5110 if (klass->inited || mono_class_has_failure (klass)) {
5111 mono_loader_unlock ();
5112 /* Somebody might have gotten in before us */
5113 return !mono_class_has_failure (klass);
5116 if (klass->init_pending) {
5117 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Recursive type definition detected"));
5121 klass->init_pending = 1;
5123 if (mono_verifier_is_enabled_for_class (klass) && !mono_verifier_verify_class (klass)) {
5124 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, concat_two_strings_with_zero (klass->image, klass->name, klass->image->assembly_name));
5129 if (klass->byval_arg.type == MONO_TYPE_ARRAY || klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5130 MonoClass *element_class = klass->element_class;
5131 if (!element_class->inited)
5132 mono_class_init (element_class);
5133 if (mono_class_has_failure (element_class)) {
5134 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5139 mono_stats.initialized_class_count++;
5141 if (klass->generic_class && !klass->generic_class->is_dynamic) {
5142 MonoClass *gklass = klass->generic_class->container_class;
5144 mono_stats.generic_class_count++;
5146 klass->method = gklass->method;
5147 klass->field = gklass->field;
5149 mono_class_init (gklass);
5150 // FIXME: Why is this needed ?
5151 if (!mono_class_has_failure (gklass))
5152 mono_class_setup_methods (gklass);
5153 if (mono_class_has_failure (gklass)) {
5154 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic Type Defintion failed to init"));
5158 if (MONO_CLASS_IS_INTERFACE (klass))
5159 klass->interface_id = mono_get_unique_iid (klass);
5162 if (klass->parent && !klass->parent->inited)
5163 mono_class_init (klass->parent);
5165 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
5167 if (klass->generic_class || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
5168 klass->nested_classes_inited = TRUE;
5171 * Computes the size used by the fields, and their locations
5173 if (has_cached_info) {
5174 klass->instance_size = cached_info.instance_size;
5175 klass->sizes.class_size = cached_info.class_size;
5176 klass->packing_size = cached_info.packing_size;
5177 klass->min_align = cached_info.min_align;
5178 klass->blittable = cached_info.blittable;
5179 klass->has_references = cached_info.has_references;
5180 klass->has_static_refs = cached_info.has_static_refs;
5181 klass->no_special_static_fields = cached_info.no_special_static_fields;
5184 if (!klass->size_inited){
5185 mono_class_setup_fields (klass);
5186 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
5190 /* Initialize arrays */
5192 klass->method.count = 3 + (klass->rank > 1? 2: 1);
5194 if (klass->interface_count) {
5195 int count_generic = generic_array_methods (klass);
5196 klass->method.count += klass->interface_count * count_generic;
5200 mono_class_setup_supertypes (klass);
5203 initialize_object_slots (klass);
5206 * Initialize the rest of the data without creating a generic vtable if possible.
5207 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5208 * also avoid computing a generic vtable.
5210 if (has_cached_info) {
5212 klass->vtable_size = cached_info.vtable_size;
5213 klass->has_finalize = cached_info.has_finalize;
5214 klass->has_finalize_inited = TRUE;
5215 klass->ghcimpl = cached_info.ghcimpl;
5216 klass->has_cctor = cached_info.has_cctor;
5217 } else if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5218 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5219 * The first slot if for array with.
5221 static int szarray_vtable_size[2] = { 0 };
5223 int slot = MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg) ? 0 : 1;
5226 if (!szarray_vtable_size [slot]) {
5227 mono_class_setup_vtable (klass);
5228 szarray_vtable_size [slot] = klass->vtable_size;
5230 klass->vtable_size = szarray_vtable_size[slot];
5232 } else if (klass->generic_class && !MONO_CLASS_IS_INTERFACE (klass)) {
5233 MonoClass *gklass = klass->generic_class->container_class;
5235 /* Generic instance case */
5236 klass->ghcimpl = gklass->ghcimpl;
5237 klass->has_cctor = gklass->has_cctor;
5239 mono_class_setup_vtable (gklass);
5240 if (mono_class_has_failure (gklass)) {
5241 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5245 klass->vtable_size = gklass->vtable_size;
5249 /* ghcimpl is not currently used
5251 if (klass->parent) {
5252 MonoMethod *cmethod = klass->vtable [ghc_slot];
5253 if (cmethod->is_inflated)
5254 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5255 if (cmethod == default_ghc) {
5261 /* C# doesn't allow interfaces to have cctors */
5262 if (!MONO_CLASS_IS_INTERFACE (klass) || klass->image != mono_defaults.corlib) {
5263 MonoMethod *cmethod = NULL;
5265 if (klass->type_token && !image_is_dynamic(klass->image)) {
5266 cmethod = find_method_in_metadata (klass, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5267 /* The find_method function ignores the 'flags' argument */
5268 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5269 klass->has_cctor = 1;
5271 mono_class_setup_methods (klass);
5272 if (mono_class_has_failure (klass))
5275 for (i = 0; i < klass->method.count; ++i) {
5276 MonoMethod *method = klass->methods [i];
5277 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5278 (strcmp (".cctor", method->name) == 0)) {
5279 klass->has_cctor = 1;
5287 if (klass->parent) {
5288 int first_iface_slot;
5289 /* This will compute klass->parent->vtable_size for some classes */
5290 mono_class_init (klass->parent);
5291 if (mono_class_has_failure (klass->parent)) {
5292 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5295 if (mono_loader_get_last_error ())
5297 if (!klass->parent->vtable_size) {
5298 /* FIXME: Get rid of this somehow */
5299 mono_class_setup_vtable (klass->parent);
5300 if (mono_class_has_failure (klass->parent)) {
5301 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5304 if (mono_loader_get_last_error ())
5307 first_iface_slot = klass->parent->vtable_size;
5308 if (mono_class_need_stelemref_method (klass))
5310 setup_interface_offsets (klass, first_iface_slot, TRUE);
5312 setup_interface_offsets (klass, 0, TRUE);
5315 if (mono_security_core_clr_enabled ())
5316 mono_security_core_clr_check_inheritance (klass);
5318 if (mono_loader_get_last_error ()) {
5319 if (!mono_class_has_failure (klass)) {
5320 set_failure_from_loader_error (klass, mono_loader_get_last_error ());
5322 mono_loader_clear_error ();
5325 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass))
5326 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Invalid generic instantiation"));
5331 /* Because of the double-checking locking pattern */
5332 mono_memory_barrier ();
5334 klass->init_pending = 0;
5336 mono_loader_unlock ();
5338 return !mono_class_has_failure (klass);
5342 * mono_class_has_finalizer:
5344 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5348 mono_class_has_finalizer (MonoClass *klass)
5350 gboolean has_finalize = FALSE;
5352 if (klass->has_finalize_inited)
5353 return klass->has_finalize;
5355 /* Interfaces and valuetypes are not supposed to have finalizers */
5356 if (!(MONO_CLASS_IS_INTERFACE (klass) || klass->valuetype)) {
5357 MonoMethod *cmethod = NULL;
5359 if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5360 } else if (klass->generic_class) {
5361 MonoClass *gklass = klass->generic_class->container_class;
5363 has_finalize = mono_class_has_finalizer (gklass);
5364 } else if (klass->parent && klass->parent->has_finalize) {
5365 has_finalize = TRUE;
5367 if (klass->parent) {
5369 * Can't search in metadata for a method named Finalize, because that
5370 * ignores overrides.
5372 mono_class_setup_vtable (klass);
5373 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
5376 cmethod = klass->vtable [finalize_slot];
5380 g_assert (klass->vtable_size > finalize_slot);
5382 if (klass->parent) {
5383 if (cmethod->is_inflated)
5384 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5385 if (cmethod != default_finalize)
5386 has_finalize = TRUE;
5392 mono_image_lock (klass->image);
5394 if (!klass->has_finalize_inited) {
5395 klass->has_finalize = has_finalize ? 1 : 0;
5397 mono_memory_barrier ();
5398 klass->has_finalize_inited = TRUE;
5401 mono_image_unlock (klass->image);
5403 return klass->has_finalize;
5407 mono_is_corlib_image (MonoImage *image)
5409 /* FIXME: allow the dynamic case for our compilers and with full trust */
5410 if (image_is_dynamic (image))
5411 return image->assembly && !strcmp (image->assembly->aname.name, "mscorlib");
5413 return image == mono_defaults.corlib;
5417 * LOCKING: this assumes the loader lock is held
5420 mono_class_setup_mono_type (MonoClass *klass)
5422 const char *name = klass->name;
5423 const char *nspace = klass->name_space;
5424 gboolean is_corlib = mono_is_corlib_image (klass->image);
5426 klass->this_arg.byref = 1;
5427 klass->this_arg.data.klass = klass;
5428 klass->this_arg.type = MONO_TYPE_CLASS;
5429 klass->byval_arg.data.klass = klass;
5430 klass->byval_arg.type = MONO_TYPE_CLASS;
5432 if (is_corlib && !strcmp (nspace, "System")) {
5433 if (!strcmp (name, "ValueType")) {
5435 * do not set the valuetype bit for System.ValueType.
5436 * klass->valuetype = 1;
5438 klass->blittable = TRUE;
5439 } else if (!strcmp (name, "Enum")) {
5441 * do not set the valuetype bit for System.Enum.
5442 * klass->valuetype = 1;
5444 klass->valuetype = 0;
5445 klass->enumtype = 0;
5446 } else if (!strcmp (name, "Object")) {
5447 klass->byval_arg.type = MONO_TYPE_OBJECT;
5448 klass->this_arg.type = MONO_TYPE_OBJECT;
5449 } else if (!strcmp (name, "String")) {
5450 klass->byval_arg.type = MONO_TYPE_STRING;
5451 klass->this_arg.type = MONO_TYPE_STRING;
5452 } else if (!strcmp (name, "TypedReference")) {
5453 klass->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5454 klass->this_arg.type = MONO_TYPE_TYPEDBYREF;
5458 if (klass->valuetype) {
5459 int t = MONO_TYPE_VALUETYPE;
5461 if (is_corlib && !strcmp (nspace, "System")) {
5464 if (!strcmp (name, "Boolean")) {
5465 t = MONO_TYPE_BOOLEAN;
5466 } else if (!strcmp(name, "Byte")) {
5468 klass->blittable = TRUE;
5472 if (!strcmp (name, "Char")) {
5477 if (!strcmp (name, "Double")) {
5479 klass->blittable = TRUE;
5483 if (!strcmp (name, "Int32")) {
5485 klass->blittable = TRUE;
5486 } else if (!strcmp(name, "Int16")) {
5488 klass->blittable = TRUE;
5489 } else if (!strcmp(name, "Int64")) {
5491 klass->blittable = TRUE;
5492 } else if (!strcmp(name, "IntPtr")) {
5494 klass->blittable = TRUE;
5498 if (!strcmp (name, "Single")) {
5500 klass->blittable = TRUE;
5501 } else if (!strcmp(name, "SByte")) {
5503 klass->blittable = TRUE;
5507 if (!strcmp (name, "UInt32")) {
5509 klass->blittable = TRUE;
5510 } else if (!strcmp(name, "UInt16")) {
5512 klass->blittable = TRUE;
5513 } else if (!strcmp(name, "UInt64")) {
5515 klass->blittable = TRUE;
5516 } else if (!strcmp(name, "UIntPtr")) {
5518 klass->blittable = TRUE;
5522 if (!strcmp (name, "TypedReference")) {
5523 t = MONO_TYPE_TYPEDBYREF;
5524 klass->blittable = TRUE;
5528 if (!strcmp (name, "Void")) {
5536 klass->byval_arg.type = (MonoTypeEnum)t;
5537 klass->this_arg.type = (MonoTypeEnum)t;
5540 if (MONO_CLASS_IS_INTERFACE (klass))
5541 klass->interface_id = mono_get_unique_iid (klass);
5547 * COM initialization is delayed until needed.
5548 * However when a [ComImport] attribute is present on a type it will trigger
5549 * the initialization. This is not a problem unless the BCL being executed
5550 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5553 init_com_from_comimport (MonoClass *klass)
5555 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5556 if (mono_security_core_clr_enabled ()) {
5557 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5558 if (!mono_security_core_clr_determine_platform_image (klass->image)) {
5559 /* but it can not be made available for application (i.e. user code) since all COM calls
5560 * are considered native calls. In this case we fail with a TypeLoadException (just like
5561 * Silverlight 2 does */
5562 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5567 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5569 #endif /*DISABLE_COM*/
5572 * LOCKING: this assumes the loader lock is held
5575 mono_class_setup_parent (MonoClass *klass, MonoClass *parent)
5577 gboolean system_namespace;
5578 gboolean is_corlib = mono_is_corlib_image (klass->image);
5580 system_namespace = !strcmp (klass->name_space, "System") && is_corlib;
5582 /* if root of the hierarchy */
5583 if (system_namespace && !strcmp (klass->name, "Object")) {
5584 klass->parent = NULL;
5585 klass->instance_size = sizeof (MonoObject);
5588 if (!strcmp (klass->name, "<Module>")) {
5589 klass->parent = NULL;
5590 klass->instance_size = 0;
5594 if (!MONO_CLASS_IS_INTERFACE (klass)) {
5595 /* Imported COM Objects always derive from __ComObject. */
5597 if (MONO_CLASS_IS_IMPORT (klass)) {
5598 init_com_from_comimport (klass);
5599 if (parent == mono_defaults.object_class)
5600 parent = mono_class_get_com_object_class ();
5604 /* set the parent to something useful and safe, but mark the type as broken */
5605 parent = mono_defaults.object_class;
5606 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5609 klass->parent = parent;
5611 if (parent->generic_class && !parent->name) {
5613 * If the parent is a generic instance, we may get
5614 * called before it is fully initialized, especially
5615 * before it has its name.
5620 #ifndef DISABLE_REMOTING
5621 klass->marshalbyref = parent->marshalbyref;
5622 klass->contextbound = parent->contextbound;
5625 klass->delegate = parent->delegate;
5627 if (MONO_CLASS_IS_IMPORT (klass) || mono_class_is_com_object (parent))
5628 mono_class_set_is_com_object (klass);
5630 if (system_namespace) {
5631 #ifndef DISABLE_REMOTING
5632 if (klass->name [0] == 'M' && !strcmp (klass->name, "MarshalByRefObject"))
5633 klass->marshalbyref = 1;
5635 if (klass->name [0] == 'C' && !strcmp (klass->name, "ContextBoundObject"))
5636 klass->contextbound = 1;
5638 if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate"))
5639 klass->delegate = 1;
5642 if (klass->parent->enumtype || (mono_is_corlib_image (klass->parent->image) && (strcmp (klass->parent->name, "ValueType") == 0) &&
5643 (strcmp (klass->parent->name_space, "System") == 0)))
5644 klass->valuetype = 1;
5645 if (mono_is_corlib_image (klass->parent->image) && ((strcmp (klass->parent->name, "Enum") == 0) && (strcmp (klass->parent->name_space, "System") == 0))) {
5646 klass->valuetype = klass->enumtype = 1;
5648 /*klass->enumtype = klass->parent->enumtype; */
5650 /* initialize com types if COM interfaces are present */
5652 if (MONO_CLASS_IS_IMPORT (klass))
5653 init_com_from_comimport (klass);
5655 klass->parent = NULL;
5661 * mono_class_setup_supertypes:
5664 * Build the data structure needed to make fast type checks work.
5665 * This currently sets two fields in @class:
5666 * - idepth: distance between @class and System.Object in the type
5668 * - supertypes: array of classes: each element has a class in the hierarchy
5669 * starting from @class up to System.Object
5671 * LOCKING: This function is atomic, in case of contention we waste memory.
5674 mono_class_setup_supertypes (MonoClass *klass)
5677 MonoClass **supertypes;
5679 mono_atomic_load_acquire (supertypes, MonoClass **, &klass->supertypes);
5683 if (klass->parent && !klass->parent->supertypes)
5684 mono_class_setup_supertypes (klass->parent);
5686 klass->idepth = klass->parent->idepth + 1;
5690 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, klass->idepth);
5691 supertypes = (MonoClass **)mono_class_alloc0 (klass, sizeof (MonoClass *) * ms);
5693 if (klass->parent) {
5694 CHECKED_METADATA_WRITE_PTR ( supertypes [klass->idepth - 1] , klass );
5697 for (supertype_idx = 0; supertype_idx < klass->parent->idepth; supertype_idx++)
5698 CHECKED_METADATA_WRITE_PTR ( supertypes [supertype_idx] , klass->parent->supertypes [supertype_idx] );
5700 CHECKED_METADATA_WRITE_PTR ( supertypes [0] , klass );
5703 CHECKED_METADATA_WRITE_PTR_ATOMIC ( klass->supertypes , supertypes );
5707 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5709 MonoClass *gtd = (MonoClass*)user_data;
5710 /* Only try to fix generic instances of @gtd */
5711 if (gclass->generic_class->container_class != gtd)
5714 /* Check if the generic instance has no parent. */
5715 if (gtd->parent && !gclass->parent)
5716 mono_generic_class_setup_parent (gclass, gtd);
5722 mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char *msg)
5724 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (msg));
5725 mono_error_set_type_load_class (error, klass, msg);
5729 * mono_class_create_from_typedef:
5730 * @image: image where the token is valid
5731 * @type_token: typedef token
5732 * @error: used to return any error found while creating the type
5734 * Create the MonoClass* representing the specified type token.
5735 * @type_token must be a TypeDef token.
5737 * FIXME: don't return NULL on failure, just the the caller figure it out.
5740 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5742 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5743 MonoClass *klass, *parent = NULL;
5744 guint32 cols [MONO_TYPEDEF_SIZE];
5745 guint32 cols_next [MONO_TYPEDEF_SIZE];
5746 guint tidx = mono_metadata_token_index (type_token);
5747 MonoGenericContext *context = NULL;
5748 const char *name, *nspace;
5750 MonoClass **interfaces;
5751 guint32 field_last, method_last;
5752 guint32 nesting_tokeen;
5754 mono_error_init (error);
5756 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5757 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5758 mono_loader_assert_no_error ();
5762 mono_loader_lock ();
5764 if ((klass = (MonoClass *)mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5765 mono_loader_unlock ();
5766 mono_loader_assert_no_error ();
5770 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5772 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5773 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5775 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
5778 klass->name_space = nspace;
5780 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5782 klass->image = image;
5783 klass->type_token = type_token;
5784 klass->flags = cols [MONO_TYPEDEF_FLAGS];
5786 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
5788 classes_size += sizeof (MonoClass);
5791 * Check whether we're a generic type definition.
5793 klass->generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
5794 if (klass->generic_container) {
5795 klass->is_generic = 1;
5796 klass->generic_container->owner.klass = klass;
5797 klass->generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
5798 context = &klass->generic_container->context;
5801 if (klass->generic_container)
5802 enable_gclass_recording ();
5804 if (cols [MONO_TYPEDEF_EXTENDS]) {
5806 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5808 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5809 /*WARNING: this must satisfy mono_metadata_type_hash*/
5810 klass->this_arg.byref = 1;
5811 klass->this_arg.data.klass = klass;
5812 klass->this_arg.type = MONO_TYPE_CLASS;
5813 klass->byval_arg.data.klass = klass;
5814 klass->byval_arg.type = MONO_TYPE_CLASS;
5816 parent = mono_class_get_checked (image, parent_token, error);
5817 if (parent && context) /* Always inflate */
5818 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5820 if (parent == NULL) {
5821 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5822 goto parent_failure;
5825 for (tmp = parent; tmp; tmp = tmp->parent) {
5827 mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
5828 goto parent_failure;
5830 if (klass->generic_container && tmp->generic_class && tmp->generic_class->container_class == klass) {
5831 mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
5832 goto parent_failure;
5837 mono_class_setup_parent (klass, parent);
5839 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5840 mono_class_setup_mono_type (klass);
5842 if (klass->generic_container)
5843 disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
5846 * This might access klass->byval_arg for recursion generated by generic constraints,
5847 * so it has to come after setup_mono_type ().
5849 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5850 klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5851 if (!mono_error_ok (error)) {
5852 /*FIXME implement a mono_class_set_failure_from_mono_error */
5853 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5854 mono_loader_unlock ();
5855 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5856 mono_loader_assert_no_error ();
5861 if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5865 if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5869 klass->cast_class = klass->element_class = klass;
5871 if (!klass->enumtype) {
5872 if (!mono_metadata_interfaces_from_typedef_full (
5873 image, type_token, &interfaces, &icount, FALSE, context, error)){
5875 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5876 mono_loader_unlock ();
5877 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5881 klass->interfaces = interfaces;
5882 klass->interface_count = icount;
5883 klass->interfaces_inited = 1;
5886 /*g_print ("Load class %s\n", name);*/
5889 * Compute the field and method lists
5891 klass->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5892 klass->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5894 if (tt->rows > tidx){
5895 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5896 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5897 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5899 field_last = image->tables [MONO_TABLE_FIELD].rows;
5900 method_last = image->tables [MONO_TABLE_METHOD].rows;
5903 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5904 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5905 klass->field.count = field_last - klass->field.first;
5907 klass->field.count = 0;
5909 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5910 klass->method.count = method_last - klass->method.first;
5912 klass->method.count = 0;
5914 /* reserve space to store vector pointer in arrays */
5915 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5916 klass->instance_size += 2 * sizeof (gpointer);
5917 g_assert (klass->field.count == 0);
5920 if (klass->enumtype) {
5921 MonoType *enum_basetype = mono_class_find_enum_basetype (klass, error);
5922 if (!enum_basetype) {
5923 /*set it to a default value as the whole runtime can't handle this to be null*/
5924 klass->cast_class = klass->element_class = mono_defaults.int32_class;
5925 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5926 mono_loader_unlock ();
5927 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5928 mono_loader_assert_no_error ();
5931 klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
5935 * If we're a generic type definition, load the constraints.
5936 * We must do this after the class has been constructed to make certain recursive scenarios
5939 if (klass->generic_container && !mono_metadata_load_generic_param_constraints_checked (image, type_token, klass->generic_container, error)) {
5940 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Could not load generic parameter constrains due to %s", mono_error_get_message (error)));
5941 mono_loader_unlock ();
5942 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5943 mono_loader_assert_no_error ();
5947 if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5948 if (!strncmp (name, "Vector", 6))
5949 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");
5952 mono_loader_unlock ();
5954 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5955 mono_loader_assert_no_error ();
5960 mono_class_setup_mono_type (klass);
5961 mono_loader_unlock ();
5962 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5963 mono_loader_assert_no_error ();
5967 /** Is klass a Nullable<T> ginst? */
5969 mono_class_is_nullable (MonoClass *klass)
5971 return klass->generic_class != NULL &&
5972 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5976 /** if klass is T? return T */
5978 mono_class_get_nullable_param (MonoClass *klass)
5980 g_assert (mono_class_is_nullable (klass));
5981 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5985 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5989 MonoGenericClass *gclass = klass->generic_class;
5991 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5992 if (!mono_error_ok (&error)) {
5993 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5994 klass->parent = mono_defaults.object_class;
5995 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5996 mono_error_cleanup (&error);
6000 mono_class_setup_parent (klass, klass->parent);
6002 if (klass->enumtype) {
6003 klass->cast_class = gtd->cast_class;
6004 klass->element_class = gtd->element_class;
6010 * Create the `MonoClass' for an instantiation of a generic type.
6011 * We only do this if we actually need it.
6014 mono_generic_class_get_class (MonoGenericClass *gclass)
6016 MonoClass *klass, *gklass;
6018 if (gclass->cached_class)
6019 return gclass->cached_class;
6021 mono_loader_lock ();
6022 if (gclass->cached_class) {
6023 mono_loader_unlock ();
6024 return gclass->cached_class;
6027 klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
6029 gklass = gclass->container_class;
6031 if (record_gclass_instantiation > 0)
6032 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
6034 if (gklass->nested_in) {
6035 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
6036 klass->nested_in = gklass->nested_in;
6039 klass->name = gklass->name;
6040 klass->name_space = gklass->name_space;
6042 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6044 klass->image = gklass->image;
6045 klass->flags = gklass->flags;
6046 klass->type_token = gklass->type_token;
6047 klass->field.count = gklass->field.count;
6049 klass->is_inflated = 1;
6050 klass->generic_class = gclass;
6052 klass->byval_arg.type = MONO_TYPE_GENERICINST;
6053 klass->this_arg.type = klass->byval_arg.type;
6054 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
6055 klass->this_arg.byref = TRUE;
6056 klass->enumtype = gklass->enumtype;
6057 klass->valuetype = gklass->valuetype;
6059 klass->cast_class = klass->element_class = klass;
6061 if (mono_class_is_nullable (klass))
6062 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
6065 * We're not interested in the nested classes of a generic instance.
6066 * We use the generic type definition to look for nested classes.
6069 mono_generic_class_setup_parent (klass, gklass);
6071 if (gclass->is_dynamic) {
6073 * 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.
6074 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
6075 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
6077 if (!gklass->wastypebuilder)
6080 mono_class_setup_supertypes (klass);
6082 if (klass->enumtype) {
6084 * For enums, gklass->fields might not been set, but instance_size etc. is
6085 * already set in mono_reflection_create_internal_class (). For non-enums,
6086 * these will be computed normally in mono_class_layout_fields ().
6088 klass->instance_size = gklass->instance_size;
6089 klass->sizes.class_size = gklass->sizes.class_size;
6090 mono_memory_barrier ();
6091 klass->size_inited = 1;
6095 mono_memory_barrier ();
6096 gclass->cached_class = klass;
6098 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6100 inflated_classes ++;
6101 inflated_classes_size += sizeof (MonoClass);
6103 mono_loader_unlock ();
6109 get_image_for_container (MonoGenericContainer *container)
6112 if (container->is_anonymous) {
6113 result = container->owner.image;
6116 if (container->is_method) {
6117 MonoMethod *method = container->owner.method;
6118 g_assert_checked (method);
6119 klass = method->klass;
6121 klass = container->owner.klass;
6123 g_assert_checked (klass);
6124 result = klass->image;
6131 get_image_for_generic_param (MonoGenericParam *param)
6133 MonoGenericContainer *container = mono_generic_param_owner (param);
6134 g_assert_checked (container);
6135 return get_image_for_container (container);
6138 // Make a string in the designated image consisting of a single integer.
6139 #define INT_STRING_SIZE 16
6141 make_generic_name_string (MonoImage *image, int num)
6143 char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
6144 g_snprintf (name, INT_STRING_SIZE, "%d", num);
6148 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
6149 // pinfo is derived from param by the caller for us.
6151 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
6153 MonoClass *klass, **ptr;
6155 MonoGenericContainer *container = mono_generic_param_owner (param);
6156 g_assert_checked (container);
6158 MonoImage *image = get_image_for_container (container);
6159 gboolean is_mvar = container->is_method;
6160 gboolean is_anonymous = container->is_anonymous;
6162 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6163 classes_size += sizeof (MonoClass);
6166 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
6168 int n = mono_generic_param_num (param);
6169 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
6173 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , "" );
6174 } else if (is_mvar) {
6175 MonoMethod *omethod = container->owner.method;
6176 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
6178 MonoClass *oklass = container->owner.klass;
6179 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
6182 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6184 // Count non-NULL items in pinfo->constraints
6187 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6191 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6192 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
6194 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
6195 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
6197 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
6200 if (count - pos > 0) {
6201 klass->interface_count = count - pos;
6202 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
6203 klass->interfaces_inited = TRUE;
6204 for (i = pos; i < count; i++)
6205 CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
6208 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
6210 klass->inited = TRUE;
6211 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class , klass );
6212 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
6213 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
6215 klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6216 klass->this_arg.type = klass->byval_arg.type;
6217 CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param , param );
6218 CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
6219 klass->this_arg.byref = TRUE;
6221 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6222 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6224 /*Init these fields to sane values*/
6225 klass->min_align = 1;
6227 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6228 * constrained to, the JIT depends on this.
6230 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6231 mono_memory_barrier ();
6232 klass->size_inited = 1;
6233 klass->setup_fields_called = 1;
6235 mono_class_setup_supertypes (klass);
6237 if (count - pos > 0) {
6238 mono_class_setup_vtable (klass->parent);
6239 if (mono_class_has_failure (klass->parent))
6240 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
6242 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6248 #define FAST_CACHE_SIZE 16
6251 * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6252 * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6253 * we cache the MonoClasses.
6254 * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6255 * LOCKING: Takes the image lock depending on @take_lock.
6258 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6260 int n = mono_generic_param_num (param);
6261 MonoImage *image = get_image_for_generic_param (param);
6262 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6263 MonoClass *klass = NULL;
6268 // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6269 // For high numbers or constraints we have to use pointer hashes.
6270 if (param->gshared_constraint) {
6271 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6274 mono_image_lock (image);
6275 klass = (MonoClass *)g_hash_table_lookup (ht, param);
6277 mono_image_unlock (image);
6282 if (n < FAST_CACHE_SIZE) {
6284 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6286 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6288 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6291 mono_image_lock (image);
6292 klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6294 mono_image_unlock (image);
6301 * LOCKING: Image lock (param->image) must be held
6304 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6306 int n = mono_generic_param_num (param);
6307 MonoImage *image = get_image_for_generic_param (param);
6308 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6312 if (param->gshared_constraint) {
6313 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6315 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6316 mono_memory_barrier ();
6318 image->mvar_cache_constrained = ht;
6320 image->var_cache_constrained = ht;
6322 g_hash_table_insert (ht, param, klass);
6323 } else if (n < FAST_CACHE_SIZE) {
6325 /* Requires locking to avoid droping an already published class */
6326 if (!image->mvar_cache_fast)
6327 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6328 image->mvar_cache_fast [n] = klass;
6330 if (!image->var_cache_fast)
6331 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6332 image->var_cache_fast [n] = klass;
6335 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6337 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6339 ht = g_hash_table_new (NULL, NULL);
6340 mono_memory_barrier ();
6342 image->mvar_cache_slow = ht;
6344 image->var_cache_slow = ht;
6347 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6352 * LOCKING: Acquires the image lock (@image).
6355 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6357 MonoImage *image = get_image_for_generic_param (param);
6358 MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6359 MonoClass *klass, *klass2;
6361 // If a klass already exists for this object and is cached, return it.
6362 if (pinfo) // Non-anonymous
6363 klass = pinfo->pklass;
6365 klass = get_anon_gparam_class (param, TRUE);
6370 // Create a new klass
6371 klass = make_generic_param_class (param, pinfo);
6373 // Now we need to cache the klass we created.
6374 // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6375 // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6376 // and allow our newly-created klass object to just leak.
6377 mono_memory_barrier ();
6379 mono_image_lock (image);
6381 // Here "klass2" refers to the klass potentially created by the other thread.
6382 if (pinfo) // Repeat check from above
6383 klass2 = pinfo->pklass;
6385 klass2 = get_anon_gparam_class (param, FALSE);
6392 pinfo->pklass = klass;
6394 set_anon_gparam_class (param, klass);
6396 mono_image_unlock (image);
6398 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6400 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED); // Alert profiler about botched class create
6402 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6408 * mono_class_from_generic_parameter:
6409 * @param: Parameter to find/construct a class for.
6410 * @arg2: Is ignored.
6411 * @arg3: Is ignored.
6414 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6416 return mono_class_from_generic_parameter_internal (param);
6421 mono_ptr_class_get (MonoType *type)
6424 MonoClass *el_class;
6428 el_class = mono_class_from_mono_type (type);
6429 image = el_class->image;
6431 mono_image_lock (image);
6432 if (image->ptr_cache) {
6433 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6434 mono_image_unlock (image);
6438 mono_image_unlock (image);
6440 result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6442 classes_size += sizeof (MonoClass);
6444 result->parent = NULL; /* no parent for PTR types */
6445 result->name_space = el_class->name_space;
6446 name = g_strdup_printf ("%s*", el_class->name);
6447 result->name = mono_image_strdup (image, name);
6450 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6452 result->image = el_class->image;
6453 result->inited = TRUE;
6454 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6455 /* Can pointers get boxed? */
6456 result->instance_size = sizeof (gpointer);
6457 result->cast_class = result->element_class = el_class;
6458 result->blittable = TRUE;
6460 result->byval_arg.type = MONO_TYPE_PTR;
6461 result->this_arg.type = result->byval_arg.type;
6462 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6463 result->this_arg.byref = TRUE;
6465 mono_class_setup_supertypes (result);
6467 mono_image_lock (image);
6468 if (image->ptr_cache) {
6470 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6471 mono_image_unlock (image);
6472 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6476 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6478 g_hash_table_insert (image->ptr_cache, el_class, result);
6479 mono_image_unlock (image);
6481 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6487 mono_fnptr_class_get (MonoMethodSignature *sig)
6490 static GHashTable *ptr_hash = NULL;
6492 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6494 mono_loader_lock ();
6497 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6499 if ((result = (MonoClass *)g_hash_table_lookup (ptr_hash, sig))) {
6500 mono_loader_unlock ();
6503 result = g_new0 (MonoClass, 1);
6505 result->parent = NULL; /* no parent for PTR types */
6506 result->name_space = "System";
6507 result->name = "MonoFNPtrFakeClass";
6509 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6511 result->image = mono_defaults.corlib; /* need to fix... */
6512 result->inited = TRUE;
6513 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6514 /* Can pointers get boxed? */
6515 result->instance_size = sizeof (gpointer);
6516 result->cast_class = result->element_class = result;
6517 result->blittable = TRUE;
6519 result->byval_arg.type = MONO_TYPE_FNPTR;
6520 result->this_arg.type = result->byval_arg.type;
6521 result->this_arg.data.method = result->byval_arg.data.method = sig;
6522 result->this_arg.byref = TRUE;
6523 result->blittable = TRUE;
6525 mono_class_setup_supertypes (result);
6527 g_hash_table_insert (ptr_hash, sig, result);
6529 mono_loader_unlock ();
6531 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6537 * mono_class_from_mono_type:
6538 * @type: describes the type to return
6540 * This returns a MonoClass for the specified MonoType, the value is never NULL.
6543 mono_class_from_mono_type (MonoType *type)
6545 switch (type->type) {
6546 case MONO_TYPE_OBJECT:
6547 return type->data.klass? type->data.klass: mono_defaults.object_class;
6548 case MONO_TYPE_VOID:
6549 return type->data.klass? type->data.klass: mono_defaults.void_class;
6550 case MONO_TYPE_BOOLEAN:
6551 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6552 case MONO_TYPE_CHAR:
6553 return type->data.klass? type->data.klass: mono_defaults.char_class;
6555 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6557 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6559 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6561 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6563 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6565 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6567 return type->data.klass? type->data.klass: mono_defaults.int_class;
6569 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6571 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6573 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6575 return type->data.klass? type->data.klass: mono_defaults.single_class;
6577 return type->data.klass? type->data.klass: mono_defaults.double_class;
6578 case MONO_TYPE_STRING:
6579 return type->data.klass? type->data.klass: mono_defaults.string_class;
6580 case MONO_TYPE_TYPEDBYREF:
6581 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6582 case MONO_TYPE_ARRAY:
6583 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6585 return mono_ptr_class_get (type->data.type);
6586 case MONO_TYPE_FNPTR:
6587 return mono_fnptr_class_get (type->data.method);
6588 case MONO_TYPE_SZARRAY:
6589 return mono_array_class_get (type->data.klass, 1);
6590 case MONO_TYPE_CLASS:
6591 case MONO_TYPE_VALUETYPE:
6592 return type->data.klass;
6593 case MONO_TYPE_GENERICINST:
6594 return mono_generic_class_get_class (type->data.generic_class);
6595 case MONO_TYPE_MVAR:
6597 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6599 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6600 g_assert_not_reached ();
6603 // Yes, this returns NULL, even if it is documented as not doing so, but there
6604 // is no way for the code to make it this far, due to the assert above.
6609 * mono_type_retrieve_from_typespec
6610 * @image: context where the image is created
6611 * @type_spec: typespec token
6612 * @context: the generic context used to evaluate generic instantiations in
6615 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6617 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6619 *did_inflate = FALSE;
6624 if (context && (context->class_inst || context->method_inst)) {
6625 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6627 if (!mono_error_ok (error)) {
6628 mono_loader_assert_no_error ();
6634 *did_inflate = TRUE;
6641 * mono_class_create_from_typespec
6642 * @image: context where the image is created
6643 * @type_spec: typespec token
6644 * @context: the generic context used to evaluate generic instantiations in
6647 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6650 gboolean inflated = FALSE;
6651 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6652 return_val_if_nok (error, NULL);
6653 ret = mono_class_from_mono_type (t);
6655 mono_metadata_free_type (t);
6660 * mono_bounded_array_class_get:
6661 * @element_class: element class
6662 * @rank: the dimension of the array class
6663 * @bounded: whenever the array has non-zero bounds
6665 * Returns: A class object describing the array with element type @element_type and
6669 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6673 MonoClass *parent = NULL;
6674 GSList *list, *rootlist = NULL;
6677 gboolean corlib_type = FALSE;
6679 g_assert (rank <= 255);
6682 /* bounded only matters for one-dimensional arrays */
6685 image = eclass->image;
6687 if (rank == 1 && !bounded) {
6689 * This case is very frequent not just during compilation because of calls
6690 * from mono_class_from_mono_type (), mono_array_new (),
6691 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6693 mono_os_mutex_lock (&image->szarray_cache_lock);
6694 if (!image->szarray_cache)
6695 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6696 klass = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6697 mono_os_mutex_unlock (&image->szarray_cache_lock);
6701 mono_loader_lock ();
6703 mono_loader_lock ();
6705 if (!image->array_cache)
6706 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6708 if ((rootlist = list = (GSList *)g_hash_table_lookup (image->array_cache, eclass))) {
6709 for (; list; list = list->next) {
6710 klass = (MonoClass *)list->data;
6711 if ((klass->rank == rank) && (klass->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6712 mono_loader_unlock ();
6719 /* for the building corlib use System.Array from it */
6720 if (image->assembly && assembly_is_dynamic (image->assembly) && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6721 parent = mono_class_load_from_name (image, "System", "Array");
6724 parent = mono_defaults.array_class;
6725 if (!parent->inited)
6726 mono_class_init (parent);
6729 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6731 klass->image = image;
6732 klass->name_space = eclass->name_space;
6733 nsize = strlen (eclass->name);
6734 name = (char *)g_malloc (nsize + 2 + rank + 1);
6735 memcpy (name, eclass->name, nsize);
6738 memset (name + nsize + 1, ',', rank - 1);
6740 name [nsize + rank] = '*';
6741 name [nsize + rank + bounded] = ']';
6742 name [nsize + rank + bounded + 1] = 0;
6743 klass->name = mono_image_strdup (image, name);
6746 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6748 classes_size += sizeof (MonoClass);
6750 klass->type_token = 0;
6751 /* all arrays are marked serializable and sealed, bug #42779 */
6752 klass->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6753 klass->parent = parent;
6754 klass->instance_size = mono_class_instance_size (klass->parent);
6756 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6757 /*Arrays of those two types are invalid.*/
6758 mono_class_set_failure (klass, MONO_EXCEPTION_INVALID_PROGRAM, NULL);
6759 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6760 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6761 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6762 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6764 /* element_size -1 is ok as this is not an instantitable type*/
6765 klass->sizes.element_size = -1;
6767 klass->sizes.element_size = mono_class_array_element_size (eclass);
6769 mono_class_setup_supertypes (klass);
6771 if (eclass->generic_class)
6772 mono_class_init (eclass);
6773 if (!eclass->size_inited)
6774 mono_class_setup_fields (eclass);
6775 if (mono_class_has_failure (eclass)) /*FIXME we fail the array type, but we have to let other fields be set.*/
6776 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
6778 klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6782 if (eclass->enumtype)
6783 klass->cast_class = eclass->element_class;
6785 klass->cast_class = eclass;
6787 switch (klass->cast_class->byval_arg.type) {
6789 klass->cast_class = mono_defaults.byte_class;
6792 klass->cast_class = mono_defaults.int16_class;
6795 #if SIZEOF_VOID_P == 4
6799 klass->cast_class = mono_defaults.int32_class;
6802 #if SIZEOF_VOID_P == 8
6806 klass->cast_class = mono_defaults.int64_class;
6812 klass->element_class = eclass;
6814 if ((rank > 1) || bounded) {
6815 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6816 klass->byval_arg.type = MONO_TYPE_ARRAY;
6817 klass->byval_arg.data.array = at;
6818 at->eklass = eclass;
6820 /* FIXME: complete.... */
6822 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6823 klass->byval_arg.data.klass = eclass;
6825 klass->this_arg = klass->byval_arg;
6826 klass->this_arg.byref = 1;
6831 klass->generic_container = eclass->generic_container;
6833 if (rank == 1 && !bounded) {
6834 MonoClass *prev_class;
6836 mono_os_mutex_lock (&image->szarray_cache_lock);
6837 prev_class = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6839 /* Someone got in before us */
6842 g_hash_table_insert (image->szarray_cache, eclass, klass);
6843 mono_os_mutex_unlock (&image->szarray_cache_lock);
6845 list = g_slist_append (rootlist, klass);
6846 g_hash_table_insert (image->array_cache, eclass, list);
6849 mono_loader_unlock ();
6851 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6857 * mono_array_class_get:
6858 * @element_class: element class
6859 * @rank: the dimension of the array class
6861 * Returns: A class object describing the array with element type @element_type and
6865 mono_array_class_get (MonoClass *eclass, guint32 rank)
6867 return mono_bounded_array_class_get (eclass, rank, FALSE);
6871 * mono_class_instance_size:
6874 * Use to get the size of a class in bytes.
6876 * Returns: The size of an object instance
6879 mono_class_instance_size (MonoClass *klass)
6881 if (!klass->size_inited)
6882 mono_class_init (klass);
6884 return klass->instance_size;
6888 * mono_class_min_align:
6891 * Use to get the computed minimum alignment requirements for the specified class.
6893 * Returns: minimm alignment requirements
6896 mono_class_min_align (MonoClass *klass)
6898 if (!klass->size_inited)
6899 mono_class_init (klass);
6901 return klass->min_align;
6905 * mono_class_value_size:
6908 * This function is used for value types, and return the
6909 * space and the alignment to store that kind of value object.
6911 * Returns: the size of a value of kind @klass
6914 mono_class_value_size (MonoClass *klass, guint32 *align)
6918 /* fixme: check disable, because we still have external revereces to
6919 * mscorlib and Dummy Objects
6921 /*g_assert (klass->valuetype);*/
6923 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6926 *align = klass->min_align;
6932 * mono_class_data_size:
6935 * Returns: The size of the static class data
6938 mono_class_data_size (MonoClass *klass)
6941 mono_class_init (klass);
6942 /* This can happen with dynamically created types */
6943 if (!klass->fields_inited)
6944 mono_class_setup_fields_locking (klass);
6946 /* in arrays, sizes.class_size is unioned with element_size
6947 * and arrays have no static fields
6951 return klass->sizes.class_size;
6955 * Auxiliary routine to mono_class_get_field
6957 * Takes a field index instead of a field token.
6959 static MonoClassField *
6960 mono_class_get_field_idx (MonoClass *klass, int idx)
6962 mono_class_setup_fields_locking (klass);
6963 if (mono_class_has_failure (klass))
6967 if (klass->image->uncompressed_metadata) {
6969 * klass->field.first points to the FieldPtr table, while idx points into the
6970 * Field table, so we have to do a search.
6972 /*FIXME this is broken for types with multiple fields with the same name.*/
6973 const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6976 for (i = 0; i < klass->field.count; ++i)
6977 if (mono_field_get_name (&klass->fields [i]) == name)
6978 return &klass->fields [i];
6979 g_assert_not_reached ();
6981 if (klass->field.count) {
6982 if ((idx >= klass->field.first) && (idx < klass->field.first + klass->field.count)){
6983 return &klass->fields [idx - klass->field.first];
6987 klass = klass->parent;
6993 * mono_class_get_field:
6994 * @class: the class to lookup the field.
6995 * @field_token: the field token
6997 * Returns: A MonoClassField representing the type and offset of
6998 * the field, or a NULL value if the field does not belong to this
7002 mono_class_get_field (MonoClass *klass, guint32 field_token)
7004 int idx = mono_metadata_token_index (field_token);
7006 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
7008 return mono_class_get_field_idx (klass, idx - 1);
7012 * mono_class_get_field_from_name:
7013 * @klass: the class to lookup the field.
7014 * @name: the field name
7016 * Search the class @klass and it's parents for a field with the name @name.
7018 * Returns: The MonoClassField pointer of the named field or NULL
7021 mono_class_get_field_from_name (MonoClass *klass, const char *name)
7023 return mono_class_get_field_from_name_full (klass, name, NULL);
7027 * mono_class_get_field_from_name_full:
7028 * @klass: the class to lookup the field.
7029 * @name: the field name
7030 * @type: the type of the fields. This optional.
7032 * Search the class @klass and it's parents for a field with the name @name and type @type.
7034 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
7035 * of its generic type definition.
7037 * Returns: The MonoClassField pointer of the named field or NULL
7040 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
7044 mono_class_setup_fields_locking (klass);
7045 if (mono_class_has_failure (klass))
7049 for (i = 0; i < klass->field.count; ++i) {
7050 MonoClassField *field = &klass->fields [i];
7052 if (strcmp (name, mono_field_get_name (field)) != 0)
7056 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
7057 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
7062 klass = klass->parent;
7068 * mono_class_get_field_token:
7069 * @field: the field we need the token of
7071 * Get the token of a field. Note that the tokesn is only valid for the image
7072 * the field was loaded from. Don't use this function for fields in dynamic types.
7074 * Returns: The token representing the field in the image it was loaded from.
7077 mono_class_get_field_token (MonoClassField *field)
7079 MonoClass *klass = field->parent;
7082 mono_class_setup_fields_locking (klass);
7087 for (i = 0; i < klass->field.count; ++i) {
7088 if (&klass->fields [i] == field) {
7089 int idx = klass->field.first + i + 1;
7091 if (klass->image->uncompressed_metadata)
7092 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
7093 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
7096 klass = klass->parent;
7099 g_assert_not_reached ();
7104 mono_field_get_index (MonoClassField *field)
7106 int index = field - field->parent->fields;
7108 g_assert (index >= 0 && index < field->parent->field.count);
7114 * mono_class_get_field_default_value:
7116 * Return the default value of the field as a pointer into the metadata blob.
7119 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
7122 guint32 constant_cols [MONO_CONSTANT_SIZE];
7124 MonoClass *klass = field->parent;
7126 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7128 if (!klass->ext || !klass->ext->field_def_values) {
7129 MonoFieldDefaultValue *def_values;
7131 mono_class_alloc_ext (klass);
7133 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
7135 mono_image_lock (klass->image);
7136 mono_memory_barrier ();
7137 if (!klass->ext->field_def_values)
7138 klass->ext->field_def_values = def_values;
7139 mono_image_unlock (klass->image);
7142 field_index = mono_field_get_index (field);
7144 if (!klass->ext->field_def_values [field_index].data) {
7145 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7149 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7151 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7152 klass->ext->field_def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7153 klass->ext->field_def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7156 *def_type = klass->ext->field_def_values [field_index].def_type;
7157 return klass->ext->field_def_values [field_index].data;
7161 mono_property_get_index (MonoProperty *prop)
7163 int index = prop - prop->parent->ext->properties;
7165 g_assert (index >= 0 && index < prop->parent->ext->property.count);
7171 * mono_class_get_property_default_value:
7173 * Return the default value of the field as a pointer into the metadata blob.
7176 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7179 guint32 constant_cols [MONO_CONSTANT_SIZE];
7180 MonoClass *klass = property->parent;
7182 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7184 * We don't cache here because it is not used by C# so it's quite rare, but
7185 * we still do the lookup in klass->ext because that is where the data
7186 * is stored for dynamic assemblies.
7189 if (image_is_dynamic (klass->image)) {
7190 int prop_index = mono_property_get_index (property);
7191 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
7192 *def_type = klass->ext->prop_def_values [prop_index].def_type;
7193 return klass->ext->prop_def_values [prop_index].data;
7197 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7201 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7202 *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7203 return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7207 mono_class_get_event_token (MonoEvent *event)
7209 MonoClass *klass = event->parent;
7214 for (i = 0; i < klass->ext->event.count; ++i) {
7215 if (&klass->ext->events [i] == event)
7216 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
7219 klass = klass->parent;
7222 g_assert_not_reached ();
7227 * mono_class_get_property_from_name:
7229 * @name: name of the property to lookup in the specified class
7231 * Use this method to lookup a property in a class
7232 * Returns: the MonoProperty with the given name, or NULL if the property
7233 * does not exist on the @klass.
7236 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7240 gpointer iter = NULL;
7241 while ((p = mono_class_get_properties (klass, &iter))) {
7242 if (! strcmp (name, p->name))
7245 klass = klass->parent;
7251 * mono_class_get_property_token:
7252 * @prop: MonoProperty to query
7254 * Returns: The ECMA token for the specified property.
7257 mono_class_get_property_token (MonoProperty *prop)
7259 MonoClass *klass = prop->parent;
7263 gpointer iter = NULL;
7264 while ((p = mono_class_get_properties (klass, &iter))) {
7265 if (&klass->ext->properties [i] == prop)
7266 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
7270 klass = klass->parent;
7273 g_assert_not_reached ();
7278 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7280 const char *name, *nspace;
7281 if (image_is_dynamic (image))
7282 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7284 switch (type_token & 0xff000000){
7285 case MONO_TOKEN_TYPE_DEF: {
7286 guint32 cols [MONO_TYPEDEF_SIZE];
7287 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7288 guint tidx = mono_metadata_token_index (type_token);
7290 if (tidx > tt->rows)
7291 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7293 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7294 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7295 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7296 if (strlen (nspace) == 0)
7297 return g_strdup_printf ("%s", name);
7299 return g_strdup_printf ("%s.%s", nspace, name);
7302 case MONO_TOKEN_TYPE_REF: {
7304 guint32 cols [MONO_TYPEREF_SIZE];
7305 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7306 guint tidx = mono_metadata_token_index (type_token);
7309 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7311 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7312 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7313 mono_error_cleanup (&error);
7317 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7318 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7319 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7320 if (strlen (nspace) == 0)
7321 return g_strdup_printf ("%s", name);
7323 return g_strdup_printf ("%s.%s", nspace, name);
7326 case MONO_TOKEN_TYPE_SPEC:
7327 return g_strdup_printf ("Typespec 0x%08x", type_token);
7329 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7334 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7336 if (image_is_dynamic (image))
7337 return g_strdup_printf ("DynamicAssembly %s", image->name);
7339 switch (type_token & 0xff000000){
7340 case MONO_TOKEN_TYPE_DEF:
7341 if (image->assembly)
7342 return mono_stringify_assembly_name (&image->assembly->aname);
7343 else if (image->assembly_name)
7344 return g_strdup (image->assembly_name);
7345 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7346 case MONO_TOKEN_TYPE_REF: {
7348 MonoAssemblyName aname;
7349 guint32 cols [MONO_TYPEREF_SIZE];
7350 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7351 guint32 idx = mono_metadata_token_index (type_token);
7354 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7356 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7357 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7358 mono_error_cleanup (&error);
7361 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7363 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7364 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7365 case MONO_RESOLUTION_SCOPE_MODULE:
7367 return g_strdup ("");
7368 case MONO_RESOLUTION_SCOPE_MODULEREF:
7370 return g_strdup ("");
7371 case MONO_RESOLUTION_SCOPE_TYPEREF:
7373 return g_strdup ("");
7374 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7375 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7376 return mono_stringify_assembly_name (&aname);
7378 g_assert_not_reached ();
7382 case MONO_TOKEN_TYPE_SPEC:
7384 return g_strdup ("");
7386 g_assert_not_reached ();
7393 * mono_class_get_full:
7394 * @image: the image where the class resides
7395 * @type_token: the token for the class
7396 * @context: the generic context used to evaluate generic instantiations in
7397 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7399 * Returns: The MonoClass that represents @type_token in @image
7402 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7406 klass = mono_class_get_checked (image, type_token, &error);
7408 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7409 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7411 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7417 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7421 mono_error_init (error);
7422 klass = mono_class_get_checked (image, type_token, error);
7424 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7425 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7430 * mono_class_get_checked:
7431 * @image: the image where the class resides
7432 * @type_token: the token for the class
7433 * @error: error object to return any error
7435 * Returns: The MonoClass that represents @type_token in @image, or NULL on error.
7438 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7440 MonoClass *klass = NULL;
7442 mono_error_init (error);
7444 if (image_is_dynamic (image)) {
7445 int table = mono_metadata_token_table (type_token);
7447 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7448 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7451 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL); /*FIXME proper error handling*/
7455 switch (type_token & 0xff000000){
7456 case MONO_TOKEN_TYPE_DEF:
7457 klass = mono_class_create_from_typedef (image, type_token, error);
7459 case MONO_TOKEN_TYPE_REF:
7460 klass = mono_class_from_typeref_checked (image, type_token, error);
7462 case MONO_TOKEN_TYPE_SPEC:
7463 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7466 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7470 /* Generic case, should be avoided for when a better error is possible. */
7471 if (!klass && mono_error_ok (error)) {
7472 char *name = mono_class_name_from_token (image, type_token);
7473 char *assembly = mono_assembly_name_from_token (image, type_token);
7474 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7482 * mono_type_get_checked:
7483 * @image: the image where the type resides
7484 * @type_token: the token for the type
7485 * @context: the generic context used to evaluate generic instantiations in
7486 * @error: Error handling context
7488 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7490 * Returns: The MonoType that represents @type_token in @image
7493 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7495 MonoType *type = NULL;
7496 gboolean inflated = FALSE;
7498 mono_error_init (error);
7500 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7501 if (image_is_dynamic (image))
7502 return mono_class_get_type ((MonoClass *)mono_lookup_dynamic_token (image, type_token, context));
7504 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7505 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7508 mono_loader_assert_no_error ();
7513 return mono_class_get_type (klass);
7516 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7519 mono_loader_assert_no_error ();
7524 MonoType *tmp = type;
7525 type = mono_class_get_type (mono_class_from_mono_type (type));
7526 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7527 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7528 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7530 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7532 if (type->type != tmp->type)
7535 mono_metadata_free_type (tmp);
7542 * @image: image where the class token will be looked up.
7543 * @type_token: a type token from the image
7545 * Returns the MonoClass with the given @type_token on the @image
7548 mono_class_get (MonoImage *image, guint32 type_token)
7550 return mono_class_get_full (image, type_token, NULL);
7554 * mono_image_init_name_cache:
7556 * Initializes the class name cache stored in image->name_cache.
7558 * LOCKING: Acquires the corresponding image lock.
7561 mono_image_init_name_cache (MonoImage *image)
7563 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7564 guint32 cols [MONO_TYPEDEF_SIZE];
7567 guint32 i, visib, nspace_index;
7568 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7570 if (image->name_cache)
7573 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7575 if (image_is_dynamic (image)) {
7576 mono_image_lock (image);
7577 if (image->name_cache) {
7578 /* Somebody initialized it before us */
7579 g_hash_table_destroy (the_name_cache);
7581 mono_atomic_store_release (&image->name_cache, the_name_cache);
7583 mono_image_unlock (image);
7587 /* Temporary hash table to avoid lookups in the nspace_table */
7588 name_cache2 = g_hash_table_new (NULL, NULL);
7590 for (i = 1; i <= t->rows; ++i) {
7591 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7592 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7594 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7595 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7597 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7599 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7600 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7602 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7603 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7604 if (!nspace_table) {
7605 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7606 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7607 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7610 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7613 /* Load type names from EXPORTEDTYPES table */
7615 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7616 guint32 cols [MONO_EXP_TYPE_SIZE];
7619 for (i = 0; i < t->rows; ++i) {
7620 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7622 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7623 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7627 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7628 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7630 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7631 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7632 if (!nspace_table) {
7633 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7634 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7635 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7638 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7642 g_hash_table_destroy (name_cache2);
7644 mono_image_lock (image);
7645 if (image->name_cache) {
7646 /* Somebody initialized it before us */
7647 g_hash_table_destroy (the_name_cache);
7649 mono_atomic_store_release (&image->name_cache, the_name_cache);
7651 mono_image_unlock (image);
7654 /*FIXME Only dynamic assemblies should allow this operation.*/
7656 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7657 const char *name, guint32 index)
7659 GHashTable *nspace_table;
7660 GHashTable *name_cache;
7663 mono_image_init_name_cache (image);
7664 mono_image_lock (image);
7666 name_cache = image->name_cache;
7667 if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7668 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7669 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7672 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7673 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7675 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7677 mono_image_unlock (image);
7686 find_nocase (gpointer key, gpointer value, gpointer user_data)
7688 char *name = (char*)key;
7689 FindUserData *data = (FindUserData*)user_data;
7691 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7692 data->value = value;
7696 * mono_class_from_name_case:
7697 * @image: The MonoImage where the type is looked up in
7698 * @name_space: the type namespace
7699 * @name: the type short name.
7700 * @deprecated: use the mono_class_from_name_case_checked variant instead.
7702 * Obtains a MonoClass with a given namespace and a given name which
7703 * is located in the given MonoImage. The namespace and name
7704 * lookups are case insensitive.
7707 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7710 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7711 mono_error_cleanup (&error);
7717 * mono_class_from_name_case:
7718 * @image: The MonoImage where the type is looked up in
7719 * @name_space: the type namespace
7720 * @name: the type short name.
7723 * Obtains a MonoClass with a given namespace and a given name which
7724 * is located in the given MonoImage. The namespace and name
7725 * lookups are case insensitive.
7727 * Returns: The MonoClass if the given namespace and name were found, or NULL if it
7728 * was not found. The @error object will contain information about the problem
7732 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7734 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7735 guint32 cols [MONO_TYPEDEF_SIZE];
7740 mono_error_init (error);
7742 if (image_is_dynamic (image)) {
7744 FindUserData user_data;
7746 mono_image_init_name_cache (image);
7747 mono_image_lock (image);
7749 user_data.key = name_space;
7750 user_data.value = NULL;
7751 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7753 if (user_data.value) {
7754 GHashTable *nspace_table = (GHashTable*)user_data.value;
7756 user_data.key = name;
7757 user_data.value = NULL;
7759 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7761 if (user_data.value)
7762 token = GPOINTER_TO_UINT (user_data.value);
7765 mono_image_unlock (image);
7768 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7774 /* add a cache if needed */
7775 for (i = 1; i <= t->rows; ++i) {
7776 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7777 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7779 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7780 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7782 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7784 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7785 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7786 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7787 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7793 return_nested_in (MonoClass *klass, char *nested)
7796 char *s = strchr (nested, '/');
7797 gpointer iter = NULL;
7804 while ((found = mono_class_get_nested_types (klass, &iter))) {
7805 if (strcmp (found->name, nested) == 0) {
7807 return return_nested_in (found, s);
7815 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7817 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7818 MonoImage *file_image;
7822 mono_error_init (error);
7825 * The EXPORTEDTYPES table only contains public types, so have to search the
7827 * Note: image->modules contains the contents of the MODULEREF table, while
7828 * the real module list is in the FILE table.
7830 for (i = 0; i < file_table->rows; i++) {
7831 guint32 cols [MONO_FILE_SIZE];
7832 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7833 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7836 file_image = mono_image_load_file_for_image (image, i + 1);
7838 klass = mono_class_from_name_checked (file_image, name_space, name, error);
7839 if (klass || !is_ok (error))
7848 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7850 GHashTable *nspace_table;
7851 MonoImage *loaded_image;
7858 mono_error_init (error);
7860 // Checking visited images avoids stack overflows when cyclic references exist.
7861 if (g_hash_table_lookup (visited_images, image))
7864 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7866 if ((nested = strchr (name, '/'))) {
7867 int pos = nested - name;
7868 int len = strlen (name);
7871 memcpy (buf, name, len + 1);
7873 nested = buf + pos + 1;
7877 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7878 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7879 gboolean res = get_class_from_name (image, name_space, name, &klass);
7882 klass = search_modules (image, name_space, name, error);
7887 return klass ? return_nested_in (klass, nested) : NULL;
7893 mono_image_init_name_cache (image);
7894 mono_image_lock (image);
7896 nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7899 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7901 mono_image_unlock (image);
7903 if (!token && image_is_dynamic (image) && image->modules) {
7904 /* Search modules as well */
7905 for (i = 0; i < image->module_count; ++i) {
7906 MonoImage *module = image->modules [i];
7908 klass = mono_class_from_name_checked (module, name_space, name, error);
7909 if (klass || !is_ok (error))
7915 klass = search_modules (image, name_space, name, error);
7916 if (klass || !is_ok (error))
7923 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7924 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7925 guint32 cols [MONO_EXP_TYPE_SIZE];
7928 idx = mono_metadata_token_index (token);
7930 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7932 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7933 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7934 loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
7937 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7939 return klass ? return_nested_in (klass, nested) : NULL;
7941 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7942 guint32 assembly_idx;
7944 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7946 mono_assembly_load_reference (image, assembly_idx - 1);
7947 g_assert (image->references [assembly_idx - 1]);
7948 if (image->references [assembly_idx - 1] == (gpointer)-1)
7950 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
7952 return klass ? return_nested_in (klass, nested) : NULL;
7955 g_assert_not_reached ();
7959 token = MONO_TOKEN_TYPE_DEF | token;
7961 klass = mono_class_get_checked (image, token, error);
7963 return return_nested_in (klass, nested);
7968 * mono_class_from_name_checked:
7969 * @image: The MonoImage where the type is looked up in
7970 * @name_space: the type namespace
7971 * @name: the type short name.
7973 * Obtains a MonoClass with a given namespace and a given name which
7974 * is located in the given MonoImage.
7976 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
7977 * set if the class was not found or it will return NULL and set the error if there was a loading error.
7980 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7983 GHashTable *visited_images;
7985 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7987 klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
7989 g_hash_table_destroy (visited_images);
7995 * mono_class_from_name:
7996 * @image: The MonoImage where the type is looked up in
7997 * @name_space: the type namespace
7998 * @name: the type short name.
8000 * Obtains a MonoClass with a given namespace and a given name which
8001 * is located in the given MonoImage.
8003 * To reference nested classes, use the "/" character as a separator.
8004 * For example use "Foo/Bar" to reference the class Bar that is nested
8005 * inside Foo, like this: "class Foo { class Bar {} }".
8008 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
8013 klass = mono_class_from_name_checked (image, name_space, name, &error);
8014 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
8020 * mono_class_load_from_name:
8021 * @image: The MonoImage where the type is looked up in
8022 * @name_space: the type namespace
8023 * @name: the type short name.
8025 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
8026 * This function should be used by the runtime for critical types to which there's no way to recover but crash
8027 * If they are missing. Thing of System.Object or System.String.
8030 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
8035 klass = mono_class_from_name_checked (image, name_space, name, &error);
8037 g_error ("Runtime critical type %s.%s not found", name_space, name);
8038 if (!mono_error_ok (&error))
8039 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8044 * mono_class_try_load_from_name:
8045 * @image: The MonoImage where the type is looked up in
8046 * @name_space: the type namespace
8047 * @name: the type short name.
8049 * This function tries to load a type, returning the class was found or NULL otherwise.
8050 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
8052 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
8053 * a type that we would otherwise assume to be available but was not due some error.
8057 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
8062 klass = mono_class_from_name_checked (image, name_space, name, &error);
8063 if (!mono_error_ok (&error))
8064 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8070 * mono_class_is_subclass_of:
8071 * @klass: class to probe if it is a subclass of another one
8072 * @klassc: the class we suspect is the base class
8073 * @check_interfaces: whether we should perform interface checks
8075 * This method determines whether @klass is a subclass of @klassc.
8077 * If the @check_interfaces flag is set, then if @klassc is an interface
8078 * this method return TRUE if the @klass implements the interface or
8079 * if @klass is an interface, if one of its base classes is @klass.
8081 * If @check_interfaces is false then, then if @klass is not an interface
8082 * then it returns TRUE if the @klass is a subclass of @klassc.
8084 * if @klass is an interface and @klassc is System.Object, then this function
8089 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
8090 gboolean check_interfaces)
8092 /*FIXME test for interfaces with variant generic arguments*/
8094 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
8095 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
8097 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
8100 for (i = 0; i < klass->interface_count; i ++) {
8101 MonoClass *ic = klass->interfaces [i];
8106 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
8111 * MS.NET thinks interfaces are a subclass of Object, so we think it as
8114 if (klassc == mono_defaults.object_class)
8121 mono_type_is_generic_argument (MonoType *type)
8123 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
8127 mono_class_has_variant_generic_params (MonoClass *klass)
8130 MonoGenericContainer *container;
8132 if (!klass->generic_class)
8135 container = klass->generic_class->container_class->generic_container;
8137 for (i = 0; i < container->type_argc; ++i)
8138 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8145 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8147 if (target == candidate)
8150 if (check_for_reference_conv &&
8151 mono_type_is_generic_argument (&target->byval_arg) &&
8152 mono_type_is_generic_argument (&candidate->byval_arg)) {
8153 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8154 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8156 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8159 if (!mono_class_is_assignable_from (target, candidate))
8165 * @container the generic container from the GTD
8166 * @klass: the class to be assigned to
8167 * @oklass: the source class
8169 * Both @klass and @oklass must be instances of the same generic interface.
8171 * Returns: TRUE if @klass can be assigned to a @klass variable
8174 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8177 MonoType **klass_argv, **oklass_argv;
8178 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8179 MonoGenericContainer *container = klass_gtd->generic_container;
8181 if (klass == oklass)
8184 /*Viable candidates are instances of the same generic interface*/
8185 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8188 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8189 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8191 for (j = 0; j < container->type_argc; ++j) {
8192 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8193 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8195 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8199 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8200 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8202 if (param1_class != param2_class) {
8203 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8204 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8206 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8207 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8217 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8219 MonoGenericParam *gparam, *ogparam;
8220 MonoGenericParamInfo *tinfo, *cinfo;
8221 MonoClass **candidate_class;
8222 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8225 if (target == candidate)
8227 if (target->byval_arg.type != candidate->byval_arg.type)
8230 gparam = target->byval_arg.data.generic_param;
8231 ogparam = candidate->byval_arg.data.generic_param;
8232 tinfo = mono_generic_param_info (gparam);
8233 cinfo = mono_generic_param_info (ogparam);
8235 class_constraint_satisfied = FALSE;
8236 valuetype_constraint_satisfied = FALSE;
8238 /*candidate must have a super set of target's special constraints*/
8239 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8240 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8242 if (cinfo->constraints) {
8243 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8244 MonoClass *cc = *candidate_class;
8246 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8247 class_constraint_satisfied = TRUE;
8248 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8249 valuetype_constraint_satisfied = TRUE;
8252 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8253 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8255 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8257 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8259 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8260 valuetype_constraint_satisfied)) {
8265 /*candidate type constraints must be a superset of target's*/
8266 if (tinfo->constraints) {
8267 MonoClass **target_class;
8268 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8269 MonoClass *tc = *target_class;
8272 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8273 * check it's constraints since it satisfy the constraint by itself.
8275 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8278 if (!cinfo->constraints)
8281 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8282 MonoClass *cc = *candidate_class;
8284 if (mono_class_is_assignable_from (tc, cc))
8288 * This happens when we have the following:
8290 * Bar<K> where K : IFace
8291 * Foo<T, U> where T : U where U : IFace
8293 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8296 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8297 if (mono_gparam_is_assignable_from (target, cc))
8301 if (!*candidate_class)
8306 /*candidate itself must have a constraint that satisfy target*/
8307 if (cinfo->constraints) {
8308 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8309 MonoClass *cc = *candidate_class;
8310 if (mono_class_is_assignable_from (target, cc))
8318 * mono_class_is_assignable_from:
8319 * @klass: the class to be assigned to
8320 * @oklass: the source class
8322 * Returns: TRUE if an instance of object oklass can be assigned to an
8323 * instance of object @klass
8326 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8328 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8330 mono_class_init (klass);
8332 if (!oklass->inited)
8333 mono_class_init (oklass);
8335 if (mono_class_has_failure (klass) || mono_class_has_failure (oklass))
8338 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8339 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8341 return mono_gparam_is_assignable_from (klass, oklass);
8344 if (MONO_CLASS_IS_INTERFACE (klass)) {
8345 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8346 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8347 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8351 for (i = 0; constraints [i]; ++i) {
8352 if (mono_class_is_assignable_from (klass, constraints [i]))
8360 /* interface_offsets might not be set for dynamic classes */
8361 if (oklass->ref_info_handle && !oklass->interface_bitmap)
8363 * oklass might be a generic type parameter but they have
8364 * interface_offsets set.
8366 return mono_reflection_call_is_assignable_to (oklass, klass);
8367 if (!oklass->interface_bitmap)
8368 /* Happens with generic instances of not-yet created dynamic types */
8370 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8373 if (mono_class_has_variant_generic_params (klass)) {
8376 mono_class_setup_interfaces (oklass, &error);
8377 if (!mono_error_ok (&error)) {
8378 mono_error_cleanup (&error);
8382 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8383 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8384 MonoClass *iface = oklass->interfaces_packed [i];
8386 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8391 } else if (klass->delegate) {
8392 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8394 }else if (klass->rank) {
8395 MonoClass *eclass, *eoclass;
8397 if (oklass->rank != klass->rank)
8400 /* vectors vs. one dimensional arrays */
8401 if (oklass->byval_arg.type != klass->byval_arg.type)
8404 eclass = klass->cast_class;
8405 eoclass = oklass->cast_class;
8408 * a is b does not imply a[] is b[] when a is a valuetype, and
8409 * b is a reference type.
8412 if (eoclass->valuetype) {
8413 if ((eclass == mono_defaults.enum_class) ||
8414 (eclass == mono_defaults.enum_class->parent) ||
8415 (eclass == mono_defaults.object_class))
8419 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8420 } else if (mono_class_is_nullable (klass)) {
8421 if (mono_class_is_nullable (oklass))
8422 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8424 return mono_class_is_assignable_from (klass->cast_class, oklass);
8425 } else if (klass == mono_defaults.object_class)
8428 return mono_class_has_parent (oklass, klass);
8431 /*Check if @oklass is variant compatible with @klass.*/
8433 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8436 MonoType **klass_argv, **oklass_argv;
8437 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8438 MonoGenericContainer *container = klass_gtd->generic_container;
8440 /*Viable candidates are instances of the same generic interface*/
8441 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8444 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8445 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8447 for (j = 0; j < container->type_argc; ++j) {
8448 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8449 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8451 if (param1_class->valuetype != param2_class->valuetype)
8455 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8456 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8458 if (param1_class != param2_class) {
8459 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8460 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8462 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8463 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8471 /*Check if @candidate implements the interface @target*/
8473 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8477 gboolean is_variant = mono_class_has_variant_generic_params (target);
8479 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8480 if (mono_class_is_variant_compatible_slow (target, candidate))
8485 if (candidate == target)
8488 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8489 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8490 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (candidate);
8492 if (tb && tb->interfaces) {
8493 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8494 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8495 MonoClass *iface_class;
8497 /* we can't realize the type here since it can do pretty much anything. */
8500 iface_class = mono_class_from_mono_type (iface->type);
8501 if (iface_class == target)
8503 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8505 if (mono_class_implement_interface_slow (target, iface_class))
8510 /*setup_interfaces don't mono_class_init anything*/
8511 /*FIXME this doesn't handle primitive type arrays.
8512 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8513 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8515 mono_class_setup_interfaces (candidate, &error);
8516 if (!mono_error_ok (&error)) {
8517 mono_error_cleanup (&error);
8521 for (i = 0; i < candidate->interface_count; ++i) {
8522 if (candidate->interfaces [i] == target)
8525 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8528 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8532 candidate = candidate->parent;
8533 } while (candidate);
8539 * Check if @oklass can be assigned to @klass.
8540 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8543 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8545 if (candidate == target)
8547 if (target == mono_defaults.object_class)
8550 if (mono_class_has_parent (candidate, target))
8553 /*If target is not an interface there is no need to check them.*/
8554 if (MONO_CLASS_IS_INTERFACE (target))
8555 return mono_class_implement_interface_slow (target, candidate);
8557 if (target->delegate && mono_class_has_variant_generic_params (target))
8558 return mono_class_is_variant_compatible (target, candidate, FALSE);
8561 MonoClass *eclass, *eoclass;
8563 if (target->rank != candidate->rank)
8566 /* vectors vs. one dimensional arrays */
8567 if (target->byval_arg.type != candidate->byval_arg.type)
8570 eclass = target->cast_class;
8571 eoclass = candidate->cast_class;
8574 * a is b does not imply a[] is b[] when a is a valuetype, and
8575 * b is a reference type.
8578 if (eoclass->valuetype) {
8579 if ((eclass == mono_defaults.enum_class) ||
8580 (eclass == mono_defaults.enum_class->parent) ||
8581 (eclass == mono_defaults.object_class))
8585 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8587 /*FIXME properly handle nullables */
8588 /*FIXME properly handle (M)VAR */
8593 * mono_class_get_cctor:
8594 * @klass: A MonoClass pointer
8596 * Returns: The static constructor of @klass if it exists, NULL otherwise.
8599 mono_class_get_cctor (MonoClass *klass)
8601 MonoCachedClassInfo cached_info;
8603 if (image_is_dynamic (klass->image)) {
8605 * has_cctor is not set for these classes because mono_class_init () is
8608 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8611 if (!klass->has_cctor)
8614 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8616 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8617 if (!mono_error_ok (&error))
8618 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8622 if (klass->generic_class && !klass->methods)
8623 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8625 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8629 * mono_class_get_finalizer:
8630 * @klass: The MonoClass pointer
8632 * Returns: The finalizer method of @klass if it exists, NULL otherwise.
8635 mono_class_get_finalizer (MonoClass *klass)
8637 MonoCachedClassInfo cached_info;
8640 mono_class_init (klass);
8641 if (!mono_class_has_finalizer (klass))
8644 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8646 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8647 if (!mono_error_ok (&error))
8648 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8651 mono_class_setup_vtable (klass);
8652 return klass->vtable [finalize_slot];
8657 * mono_class_needs_cctor_run:
8658 * @klass: the MonoClass pointer
8659 * @caller: a MonoMethod describing the caller
8661 * Determines whenever the class has a static constructor and whenever it
8662 * needs to be called when executing CALLER.
8665 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8669 method = mono_class_get_cctor (klass);
8671 return (method == caller) ? FALSE : TRUE;
8677 * mono_class_array_element_size:
8680 * Returns: The number of bytes an element of type @klass
8681 * uses when stored into an array.
8684 mono_class_array_element_size (MonoClass *klass)
8686 MonoType *type = &klass->byval_arg;
8689 switch (type->type) {
8692 case MONO_TYPE_BOOLEAN:
8696 case MONO_TYPE_CHAR:
8705 case MONO_TYPE_CLASS:
8706 case MONO_TYPE_STRING:
8707 case MONO_TYPE_OBJECT:
8708 case MONO_TYPE_SZARRAY:
8709 case MONO_TYPE_ARRAY:
8710 return sizeof (gpointer);
8715 case MONO_TYPE_VALUETYPE:
8716 if (type->data.klass->enumtype) {
8717 type = mono_class_enum_basetype (type->data.klass);
8718 klass = klass->element_class;
8721 return mono_class_instance_size (klass) - sizeof (MonoObject);
8722 case MONO_TYPE_GENERICINST:
8723 type = &type->data.generic_class->container_class->byval_arg;
8726 case MONO_TYPE_MVAR: {
8729 return mono_type_size (type, &align);
8731 case MONO_TYPE_VOID:
8735 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8741 * mono_array_element_size:
8742 * @ac: pointer to a #MonoArrayClass
8744 * Returns: The size of single array element.
8747 mono_array_element_size (MonoClass *ac)
8749 g_assert (ac->rank);
8750 return ac->sizes.element_size;
8754 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8755 MonoGenericContext *context)
8758 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8759 g_assert (mono_error_ok (&error));
8764 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8765 MonoGenericContext *context, MonoError *error)
8767 mono_error_init (error);
8769 if (image_is_dynamic (image)) {
8770 MonoClass *tmp_handle_class;
8771 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context);
8773 g_assert (tmp_handle_class);
8775 *handle_class = tmp_handle_class;
8777 if (tmp_handle_class == mono_defaults.typehandle_class)
8778 return &((MonoClass*)obj)->byval_arg;
8783 switch (token & 0xff000000) {
8784 case MONO_TOKEN_TYPE_DEF:
8785 case MONO_TOKEN_TYPE_REF:
8786 case MONO_TOKEN_TYPE_SPEC: {
8789 *handle_class = mono_defaults.typehandle_class;
8790 type = mono_type_get_checked (image, token, context, error);
8794 mono_class_init (mono_class_from_mono_type (type));
8795 /* We return a MonoType* as handle */
8798 case MONO_TOKEN_FIELD_DEF: {
8800 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8802 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8806 *handle_class = mono_defaults.fieldhandle_class;
8807 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8811 mono_class_init (klass);
8812 return mono_class_get_field (klass, token);
8814 case MONO_TOKEN_METHOD_DEF:
8815 case MONO_TOKEN_METHOD_SPEC: {
8817 meth = mono_get_method_checked (image, token, NULL, context, error);
8819 *handle_class = mono_defaults.methodhandle_class;
8825 case MONO_TOKEN_MEMBER_REF: {
8826 guint32 cols [MONO_MEMBERREF_SIZE];
8828 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8829 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8830 mono_metadata_decode_blob_size (sig, &sig);
8831 if (*sig == 0x6) { /* it's a field */
8833 MonoClassField *field;
8834 field = mono_field_from_token_checked (image, token, &klass, context, error);
8836 *handle_class = mono_defaults.fieldhandle_class;
8840 meth = mono_get_method_checked (image, token, NULL, context, error);
8842 *handle_class = mono_defaults.methodhandle_class;
8847 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8853 * This function might need to call runtime functions so it can't be part
8854 * of the metadata library.
8856 static MonoLookupDynamicToken lookup_dynamic = NULL;
8859 mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
8861 lookup_dynamic = func;
8865 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context)
8867 MonoClass *handle_class;
8869 return lookup_dynamic (image, token, TRUE, &handle_class, context);
8873 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
8875 return lookup_dynamic (image, token, valid_token, handle_class, context);
8878 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8881 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8883 get_cached_class_info = func;
8887 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8889 if (!get_cached_class_info)
8892 return get_cached_class_info (klass, res);
8896 mono_install_get_class_from_name (MonoGetClassFromName func)
8898 get_class_from_name = func;
8902 * mono_class_get_image:
8904 * Use this method to get the `MonoImage*` where this class came from.
8906 * Returns: The image where this class is defined.
8909 mono_class_get_image (MonoClass *klass)
8911 return klass->image;
8915 * mono_class_get_element_class:
8916 * @klass: the MonoClass to act on
8918 * Use this function to get the element class of an array.
8920 * Returns: The element class of an array.
8923 mono_class_get_element_class (MonoClass *klass)
8925 return klass->element_class;
8929 * mono_class_is_valuetype:
8930 * @klass: the MonoClass to act on
8932 * Use this method to determine if the provided `MonoClass*` represents a value type,
8933 * or a reference type.
8935 * Returns: TRUE if the MonoClass represents a ValueType, FALSE if it represents a reference type.
8938 mono_class_is_valuetype (MonoClass *klass)
8940 return klass->valuetype;
8944 * mono_class_is_enum:
8945 * @klass: the MonoClass to act on
8947 * Use this function to determine if the provided `MonoClass*` represents an enumeration.
8949 * Returns: TRUE if the MonoClass represents an enumeration.
8952 mono_class_is_enum (MonoClass *klass)
8954 return klass->enumtype;
8958 * mono_class_enum_basetype:
8959 * @klass: the MonoClass to act on
8961 * Use this function to get the underlying type for an enumeration value.
8963 * Returns: The underlying type representation for an enumeration.
8966 mono_class_enum_basetype (MonoClass *klass)
8968 if (klass->element_class == klass)
8969 /* SRE or broken types */
8972 return &klass->element_class->byval_arg;
8976 * mono_class_get_parent
8977 * @klass: the MonoClass to act on
8979 * Returns: The parent class for this class.
8982 mono_class_get_parent (MonoClass *klass)
8984 return klass->parent;
8988 * mono_class_get_nesting_type:
8989 * @klass: the MonoClass to act on
8991 * Use this function to obtain the class that the provided `MonoClass*` is nested on.
8993 * If the return is NULL, this indicates that this class is not nested.
8995 * Returns: The container type where this type is nested or NULL if this type is not a nested type.
8998 mono_class_get_nesting_type (MonoClass *klass)
9000 return klass->nested_in;
9004 * mono_class_get_rank:
9005 * @klass: the MonoClass to act on
9007 * Returns: The rank for the array (the number of dimensions).
9010 mono_class_get_rank (MonoClass *klass)
9016 * mono_class_get_flags:
9017 * @klass: the MonoClass to act on
9019 * The type flags from the TypeDef table from the metadata.
9020 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
9023 * Returns: The flags from the TypeDef table.
9026 mono_class_get_flags (MonoClass *klass)
9028 return klass->flags;
9032 * mono_class_get_name
9033 * @klass: the MonoClass to act on
9035 * Returns: The name of the class.
9038 mono_class_get_name (MonoClass *klass)
9044 * mono_class_get_namespace:
9045 * @klass: the MonoClass to act on
9047 * Returns: The namespace of the class.
9050 mono_class_get_namespace (MonoClass *klass)
9052 return klass->name_space;
9056 * mono_class_get_type:
9057 * @klass: the MonoClass to act on
9059 * This method returns the internal Type representation for the class.
9061 * Returns: The MonoType from the class.
9064 mono_class_get_type (MonoClass *klass)
9066 return &klass->byval_arg;
9070 * mono_class_get_type_token:
9071 * @klass: the MonoClass to act on
9073 * This method returns type token for the class.
9075 * Returns: The type token for the class.
9078 mono_class_get_type_token (MonoClass *klass)
9080 return klass->type_token;
9084 * mono_class_get_byref_type:
9085 * @klass: the MonoClass to act on
9090 mono_class_get_byref_type (MonoClass *klass)
9092 return &klass->this_arg;
9096 * mono_class_num_fields:
9097 * @klass: the MonoClass to act on
9099 * Returns: The number of static and instance fields in the class.
9102 mono_class_num_fields (MonoClass *klass)
9104 return klass->field.count;
9108 * mono_class_num_methods:
9109 * @klass: the MonoClass to act on
9111 * Returns: The number of methods in the class.
9114 mono_class_num_methods (MonoClass *klass)
9116 return klass->method.count;
9120 * mono_class_num_properties
9121 * @klass: the MonoClass to act on
9123 * Returns: The number of properties in the class.
9126 mono_class_num_properties (MonoClass *klass)
9128 mono_class_setup_properties (klass);
9130 return klass->ext->property.count;
9134 * mono_class_num_events:
9135 * @klass: the MonoClass to act on
9137 * Returns: The number of events in the class.
9140 mono_class_num_events (MonoClass *klass)
9142 mono_class_setup_events (klass);
9144 return klass->ext->event.count;
9148 * mono_class_get_fields:
9149 * @klass: the MonoClass to act on
9151 * This routine is an iterator routine for retrieving the fields in a class.
9153 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9154 * iterate over all of the elements. When no more values are
9155 * available, the return value is NULL.
9157 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
9160 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9162 MonoClassField* field;
9166 mono_class_setup_fields_locking (klass);
9167 if (mono_class_has_failure (klass))
9169 /* start from the first */
9170 if (klass->field.count) {
9171 *iter = &klass->fields [0];
9172 return &klass->fields [0];
9178 field = (MonoClassField *)*iter;
9180 if (field < &klass->fields [klass->field.count]) {
9188 * mono_class_get_methods
9189 * @klass: the MonoClass to act on
9191 * This routine is an iterator routine for retrieving the fields in a class.
9193 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9194 * iterate over all of the elements. When no more values are
9195 * available, the return value is NULL.
9197 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
9200 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9202 MonoMethod** method;
9206 mono_class_setup_methods (klass);
9209 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9210 * FIXME we should better report this error to the caller
9212 if (!klass->methods)
9214 /* start from the first */
9215 if (klass->method.count) {
9216 *iter = &klass->methods [0];
9217 return klass->methods [0];
9223 method = (MonoMethod **)*iter;
9225 if (method < &klass->methods [klass->method.count]) {
9233 * mono_class_get_virtual_methods:
9235 * Iterate over the virtual methods of KLASS.
9237 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9240 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9242 MonoMethod** method;
9245 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9247 mono_class_setup_methods (klass);
9249 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9250 * FIXME we should better report this error to the caller
9252 if (!klass->methods)
9254 /* start from the first */
9255 method = &klass->methods [0];
9257 method = (MonoMethod **)*iter;
9260 while (method < &klass->methods [klass->method.count]) {
9261 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9265 if (method < &klass->methods [klass->method.count]) {
9272 /* Search directly in metadata to avoid calling setup_methods () */
9273 MonoMethod *res = NULL;
9279 start_index = GPOINTER_TO_UINT (*iter);
9282 for (i = start_index; i < klass->method.count; ++i) {
9285 /* klass->method.first points into the methodptr table */
9286 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
9288 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9292 if (i < klass->method.count) {
9294 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9295 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9297 /* Add 1 here so the if (*iter) check fails */
9298 *iter = GUINT_TO_POINTER (i + 1);
9307 * mono_class_get_properties:
9308 * @klass: the MonoClass to act on
9310 * This routine is an iterator routine for retrieving the properties in a class.
9312 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9313 * iterate over all of the elements. When no more values are
9314 * available, the return value is NULL.
9316 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9319 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9321 MonoProperty* property;
9325 mono_class_setup_properties (klass);
9326 /* start from the first */
9327 if (klass->ext->property.count) {
9328 *iter = &klass->ext->properties [0];
9329 return (MonoProperty *)*iter;
9335 property = (MonoProperty *)*iter;
9337 if (property < &klass->ext->properties [klass->ext->property.count]) {
9339 return (MonoProperty *)*iter;
9345 * mono_class_get_events:
9346 * @klass: the MonoClass to act on
9348 * This routine is an iterator routine for retrieving the properties in a class.
9350 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9351 * iterate over all of the elements. When no more values are
9352 * available, the return value is NULL.
9354 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9357 mono_class_get_events (MonoClass* klass, gpointer *iter)
9363 mono_class_setup_events (klass);
9364 /* start from the first */
9365 if (klass->ext->event.count) {
9366 *iter = &klass->ext->events [0];
9367 return (MonoEvent *)*iter;
9373 event = (MonoEvent *)*iter;
9375 if (event < &klass->ext->events [klass->ext->event.count]) {
9377 return (MonoEvent *)*iter;
9383 * mono_class_get_interfaces
9384 * @klass: the MonoClass to act on
9386 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9388 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9389 * iterate over all of the elements. When no more values are
9390 * available, the return value is NULL.
9392 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9395 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9403 mono_class_init (klass);
9404 if (!klass->interfaces_inited) {
9405 mono_class_setup_interfaces (klass, &error);
9406 if (!mono_error_ok (&error)) {
9407 mono_error_cleanup (&error);
9411 /* start from the first */
9412 if (klass->interface_count) {
9413 *iter = &klass->interfaces [0];
9414 return klass->interfaces [0];
9420 iface = (MonoClass **)*iter;
9422 if (iface < &klass->interfaces [klass->interface_count]) {
9430 setup_nested_types (MonoClass *klass)
9433 GList *classes, *nested_classes, *l;
9436 if (klass->nested_classes_inited)
9439 if (!klass->type_token)
9440 klass->nested_classes_inited = TRUE;
9442 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9446 guint32 cols [MONO_NESTED_CLASS_SIZE];
9447 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9448 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9449 if (!mono_error_ok (&error)) {
9450 /*FIXME don't swallow the error message*/
9451 mono_error_cleanup (&error);
9453 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9457 classes = g_list_prepend (classes, nclass);
9459 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9462 mono_class_alloc_ext (klass);
9464 nested_classes = NULL;
9465 for (l = classes; l; l = l->next)
9466 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9467 g_list_free (classes);
9469 mono_image_lock (klass->image);
9471 mono_memory_barrier ();
9472 if (!klass->nested_classes_inited) {
9473 klass->ext->nested_classes = nested_classes;
9474 mono_memory_barrier ();
9475 klass->nested_classes_inited = TRUE;
9478 mono_image_unlock (klass->image);
9482 * mono_class_get_nested_types
9483 * @klass: the MonoClass to act on
9485 * This routine is an iterator routine for retrieving the nested types of a class.
9486 * This works only if @klass is non-generic, or a generic type definition.
9488 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9489 * iterate over all of the elements. When no more values are
9490 * available, the return value is NULL.
9492 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9495 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9501 if (!klass->nested_classes_inited)
9502 setup_nested_types (klass);
9505 /* start from the first */
9506 if (klass->ext && klass->ext->nested_classes) {
9507 *iter = klass->ext->nested_classes;
9508 return (MonoClass *)klass->ext->nested_classes->data;
9510 /* no nested types */
9514 item = (GList *)*iter;
9518 return (MonoClass *)item->data;
9525 * mono_class_is_delegate
9526 * @klass: the MonoClass to act on
9528 * Returns: TRUE if the MonoClass represents a System.Delegate.
9531 mono_class_is_delegate (MonoClass *klass)
9533 return klass->delegate;
9537 * mono_class_implements_interface
9538 * @klass: The MonoClass to act on
9539 * @interface: The interface to check if @klass implements.
9541 * Returns: TRUE if @klass implements @interface.
9544 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9546 return mono_class_is_assignable_from (iface, klass);
9550 * mono_field_get_name:
9551 * @field: the MonoClassField to act on
9553 * Returns: The name of the field.
9556 mono_field_get_name (MonoClassField *field)
9562 * mono_field_get_type:
9563 * @field: the MonoClassField to act on
9565 * Returns: MonoType of the field.
9568 mono_field_get_type (MonoClassField *field)
9571 MonoType *type = mono_field_get_type_checked (field, &error);
9572 if (!mono_error_ok (&error)) {
9573 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9574 mono_error_cleanup (&error);
9581 * mono_field_get_type_checked:
9582 * @field: the MonoClassField to act on
9583 * @error: used to return any erro found while retrieving @field type
9585 * Returns: MonoType of the field.
9588 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9590 mono_error_init (error);
9592 mono_field_resolve_type (field, error);
9597 * mono_field_get_parent:
9598 * @field: the MonoClassField to act on
9600 * Returns: MonoClass where the field was defined.
9603 mono_field_get_parent (MonoClassField *field)
9605 return field->parent;
9609 * mono_field_get_flags;
9610 * @field: the MonoClassField to act on
9612 * The metadata flags for a field are encoded using the
9613 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9615 * Returns: The flags for the field.
9618 mono_field_get_flags (MonoClassField *field)
9621 return mono_field_resolve_flags (field);
9622 return field->type->attrs;
9626 * mono_field_get_offset:
9627 * @field: the MonoClassField to act on
9629 * Returns: The field offset.
9632 mono_field_get_offset (MonoClassField *field)
9634 return field->offset;
9638 mono_field_get_rva (MonoClassField *field)
9642 MonoClass *klass = field->parent;
9643 MonoFieldDefaultValue *field_def_values;
9645 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9647 if (!klass->ext || !klass->ext->field_def_values) {
9648 mono_class_alloc_ext (klass);
9650 field_def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9652 mono_image_lock (klass->image);
9653 if (!klass->ext->field_def_values)
9654 klass->ext->field_def_values = field_def_values;
9655 mono_image_unlock (klass->image);
9658 field_index = mono_field_get_index (field);
9660 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9661 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9663 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9664 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9667 return klass->ext->field_def_values [field_index].data;
9671 * mono_field_get_data:
9672 * @field: the MonoClassField to act on
9674 * Returns: A pointer to the metadata constant value or to the field
9675 * data if it has an RVA flag.
9678 mono_field_get_data (MonoClassField *field)
9680 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9681 MonoTypeEnum def_type;
9683 return mono_class_get_field_default_value (field, &def_type);
9684 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9685 return mono_field_get_rva (field);
9692 * mono_property_get_name:
9693 * @prop: the MonoProperty to act on
9695 * Returns: The name of the property
9698 mono_property_get_name (MonoProperty *prop)
9704 * mono_property_get_set_method
9705 * @prop: the MonoProperty to act on.
9707 * Returns: The setter method of the property (A MonoMethod)
9710 mono_property_get_set_method (MonoProperty *prop)
9716 * mono_property_get_get_method
9717 * @prop: the MonoProperty to act on.
9719 * Returns: The setter method of the property (A MonoMethod)
9722 mono_property_get_get_method (MonoProperty *prop)
9728 * mono_property_get_parent:
9729 * @prop: the MonoProperty to act on.
9731 * Returns: The MonoClass where the property was defined.
9734 mono_property_get_parent (MonoProperty *prop)
9736 return prop->parent;
9740 * mono_property_get_flags:
9741 * @prop: the MonoProperty to act on.
9743 * The metadata flags for a property are encoded using the
9744 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9746 * Returns: The flags for the property.
9749 mono_property_get_flags (MonoProperty *prop)
9755 * mono_event_get_name:
9756 * @event: the MonoEvent to act on
9758 * Returns: The name of the event.
9761 mono_event_get_name (MonoEvent *event)
9767 * mono_event_get_add_method:
9768 * @event: The MonoEvent to act on.
9770 * Returns: The @add' method for the event (a MonoMethod).
9773 mono_event_get_add_method (MonoEvent *event)
9779 * mono_event_get_remove_method:
9780 * @event: The MonoEvent to act on.
9782 * Returns: The @remove method for the event (a MonoMethod).
9785 mono_event_get_remove_method (MonoEvent *event)
9787 return event->remove;
9791 * mono_event_get_raise_method:
9792 * @event: The MonoEvent to act on.
9794 * Returns: The @raise method for the event (a MonoMethod).
9797 mono_event_get_raise_method (MonoEvent *event)
9799 return event->raise;
9803 * mono_event_get_parent:
9804 * @event: the MonoEvent to act on.
9806 * Returns: The MonoClass where the event is defined.
9809 mono_event_get_parent (MonoEvent *event)
9811 return event->parent;
9815 * mono_event_get_flags
9816 * @event: the MonoEvent to act on.
9818 * The metadata flags for an event are encoded using the
9819 * EVENT_* constants. See the tabledefs.h file for details.
9821 * Returns: The flags for the event.
9824 mono_event_get_flags (MonoEvent *event)
9826 return event->attrs;
9830 * mono_class_get_method_from_name:
9831 * @klass: where to look for the method
9832 * @name: name of the method
9833 * @param_count: number of parameters. -1 for any number.
9835 * Obtains a MonoMethod with a given name and number of parameters.
9836 * It only works if there are no multiple signatures for any given method name.
9839 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9841 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9845 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9847 MonoMethod *res = NULL;
9850 /* Search directly in the metadata to avoid calling setup_methods () */
9851 for (i = 0; i < klass->method.count; ++i) {
9853 guint32 cols [MONO_METHOD_SIZE];
9855 MonoMethodSignature *sig;
9857 /* klass->method.first points into the methodptr table */
9858 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9860 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9861 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9863 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9866 if (param_count == -1) {
9870 sig = mono_method_signature_checked (method, &error);
9872 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9875 if (sig->param_count == param_count) {
9886 * mono_class_get_method_from_name_flags:
9887 * @klass: where to look for the method
9888 * @name_space: name of the method
9889 * @param_count: number of parameters. -1 for any number.
9890 * @flags: flags which must be set in the method
9892 * Obtains a MonoMethod with a given name and number of parameters.
9893 * It only works if there are no multiple signatures for any given method name.
9896 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9898 MonoMethod *res = NULL;
9901 mono_class_init (klass);
9903 if (klass->generic_class && !klass->methods) {
9904 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9907 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9908 if (!mono_error_ok (&error))
9909 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9914 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9915 mono_class_setup_methods (klass);
9917 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9918 See mono/tests/array_load_exception.il
9919 FIXME we should better report this error to the caller
9921 if (!klass->methods)
9923 for (i = 0; i < klass->method.count; ++i) {
9924 MonoMethod *method = klass->methods [i];
9926 if (method->name[0] == name [0] &&
9927 !strcmp (name, method->name) &&
9928 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9929 ((method->flags & flags) == flags)) {
9936 res = find_method_in_metadata (klass, name, param_count, flags);
9943 * mono_class_set_failure:
9944 * @klass: class in which the failure was detected
9945 * @ex_type: the kind of exception/error to be thrown (later)
9946 * @ex_data: exception data (specific to each type of exception/error)
9948 * Keep a detected failure informations in the class for later processing.
9949 * Note that only the first failure is kept.
9951 * LOCKING: Acquires the loader lock.
9954 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9956 if (mono_class_has_failure (klass))
9959 mono_loader_lock ();
9960 klass->exception_type = ex_type;
9962 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9963 mono_loader_unlock ();
9969 * mono_class_get_exception_data:
9971 * Return the exception_data property of KLASS.
9973 * LOCKING: Acquires the loader lock.
9976 mono_class_get_exception_data (MonoClass *klass)
9978 return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9982 * mono_classes_init:
9984 * Initialize the resources used by this module.
9987 mono_classes_init (void)
9989 mono_os_mutex_init (&classes_mutex);
9991 mono_counters_register ("Inflated methods size",
9992 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9993 mono_counters_register ("Inflated classes",
9994 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9995 mono_counters_register ("Inflated classes size",
9996 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9997 mono_counters_register ("MonoClass size",
9998 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9999 mono_counters_register ("MonoClassExt size",
10000 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
10004 * mono_classes_cleanup:
10006 * Free the resources used by this module.
10009 mono_classes_cleanup (void)
10011 if (global_interface_bitset)
10012 mono_bitset_free (global_interface_bitset);
10013 global_interface_bitset = NULL;
10014 mono_os_mutex_destroy (&classes_mutex);
10018 * mono_class_get_exception_for_failure:
10019 * @klass: class in which the failure was detected
10021 * Return a constructed MonoException than the caller can then throw
10022 * using mono_raise_exception - or NULL if no failure is present (or
10023 * doesn't result in an exception).
10026 mono_class_get_exception_for_failure (MonoClass *klass)
10028 gpointer exception_data = mono_class_get_exception_data (klass);
10030 switch (mono_class_get_failure(klass)) {
10031 case MONO_EXCEPTION_TYPE_LOAD: {
10034 char *str = mono_type_get_full_name (klass);
10035 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
10036 name = mono_string_new (mono_domain_get (), str);
10038 ex = mono_get_exception_type_load (name, astr);
10042 case MONO_EXCEPTION_MISSING_METHOD: {
10043 char *class_name = (char *)exception_data;
10044 char *assembly_name = class_name + strlen (class_name) + 1;
10046 return mono_get_exception_missing_method (class_name, assembly_name);
10048 case MONO_EXCEPTION_MISSING_FIELD: {
10049 char *class_name = (char *)exception_data;
10050 char *member_name = class_name + strlen (class_name) + 1;
10052 return mono_get_exception_missing_field (class_name, member_name);
10054 case MONO_EXCEPTION_FILE_NOT_FOUND: {
10055 char *msg_format = (char *)exception_data;
10056 char *assembly_name = msg_format + strlen (msg_format) + 1;
10057 char *msg = g_strdup_printf (msg_format, assembly_name);
10060 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
10066 case MONO_EXCEPTION_BAD_IMAGE: {
10067 return mono_get_exception_bad_image_format ((const char *)exception_data);
10069 case MONO_EXCEPTION_INVALID_PROGRAM: {
10070 return mono_exception_from_name_msg (mono_defaults.corlib, "System", "InvalidProgramException", "");
10073 MonoLoaderError *error;
10076 error = mono_loader_get_last_error ();
10077 if (error != NULL){
10078 ex = mono_loader_error_prepare_exception (error);
10082 /* TODO - handle other class related failures */
10089 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
10091 outer_klass = mono_class_get_generic_type_definition (outer_klass);
10092 inner_klass = mono_class_get_generic_type_definition (inner_klass);
10094 if (outer_klass == inner_klass)
10096 inner_klass = inner_klass->nested_in;
10097 } while (inner_klass);
10102 mono_class_get_generic_type_definition (MonoClass *klass)
10104 return klass->generic_class ? klass->generic_class->container_class : klass;
10108 * Check if @klass is a subtype of @parent ignoring generic instantiations.
10110 * Generic instantiations are ignored for all super types of @klass.
10112 * Visibility checks ignoring generic instantiations.
10115 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
10118 klass = mono_class_get_generic_type_definition (klass);
10119 parent = mono_class_get_generic_type_definition (parent);
10120 mono_class_setup_supertypes (klass);
10122 for (i = 0; i < klass->idepth; ++i) {
10123 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
10129 * Subtype can only access parent members with family protection if the site object
10130 * is subclass of Subtype. For example:
10131 * class A { protected int x; }
10133 * void valid_access () {
10137 * void invalid_access () {
10144 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
10146 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
10149 if (context_klass == NULL)
10151 /*if access_klass is not member_klass context_klass must be type compat*/
10152 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10158 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10161 if (accessing == accessed)
10163 if (!accessed || !accessing)
10166 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10167 * anywhere so untrusted friends are not safe to access platform's code internals */
10168 if (mono_security_core_clr_enabled ()) {
10169 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10173 mono_assembly_load_friends (accessed);
10174 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10175 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10176 /* Be conservative with checks */
10177 if (!friend_->name)
10179 if (strcmp (accessing->aname.name, friend_->name))
10181 if (friend_->public_key_token [0]) {
10182 if (!accessing->aname.public_key_token [0])
10184 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10193 * If klass is a generic type or if it is derived from a generic type, return the
10194 * MonoClass of the generic definition
10195 * Returns NULL if not found
10198 get_generic_definition_class (MonoClass *klass)
10201 if (klass->generic_class && klass->generic_class->container_class)
10202 return klass->generic_class->container_class;
10203 klass = klass->parent;
10209 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10212 for (i = 0; i < ginst->type_argc; ++i) {
10213 MonoType *type = ginst->type_argv[i];
10214 switch (type->type) {
10215 case MONO_TYPE_SZARRAY:
10216 if (!can_access_type (access_klass, type->data.klass))
10219 case MONO_TYPE_ARRAY:
10220 if (!can_access_type (access_klass, type->data.array->eklass))
10223 case MONO_TYPE_PTR:
10224 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10227 case MONO_TYPE_CLASS:
10228 case MONO_TYPE_VALUETYPE:
10229 case MONO_TYPE_GENERICINST:
10230 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10240 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10244 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10247 if (access_klass->element_class && !access_klass->enumtype)
10248 access_klass = access_klass->element_class;
10250 if (member_klass->element_class && !member_klass->enumtype)
10251 member_klass = member_klass->element_class;
10253 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10255 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10258 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
10261 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10264 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10267 /*Non nested type with nested visibility. We just fail it.*/
10268 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10271 switch (access_level) {
10272 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10273 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10275 case TYPE_ATTRIBUTE_PUBLIC:
10278 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10281 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10282 return is_nesting_type (member_klass, access_klass);
10284 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10285 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10287 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10288 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10290 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10291 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10292 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10294 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10295 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10296 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10301 /* FIXME: check visibility of type, too */
10303 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10305 MonoClass *member_generic_def;
10306 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10309 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
10310 access_klass->generic_container) &&
10311 (member_generic_def = get_generic_definition_class (member_klass))) {
10312 MonoClass *access_container;
10314 if (access_klass->generic_container)
10315 access_container = access_klass;
10317 access_container = access_klass->generic_class->container_class;
10319 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10323 /* Partition I 8.5.3.2 */
10324 /* the access level values are the same for fields and methods */
10325 switch (access_level) {
10326 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10327 /* same compilation unit */
10328 return access_klass->image == member_klass->image;
10329 case FIELD_ATTRIBUTE_PRIVATE:
10330 return access_klass == member_klass;
10331 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10332 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10333 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10336 case FIELD_ATTRIBUTE_ASSEMBLY:
10337 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10338 case FIELD_ATTRIBUTE_FAMILY:
10339 if (is_valid_family_access (access_klass, member_klass, context_klass))
10342 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10343 if (is_valid_family_access (access_klass, member_klass, context_klass))
10345 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10346 case FIELD_ATTRIBUTE_PUBLIC:
10353 * mono_method_can_access_field:
10354 * @method: Method that will attempt to access the field
10355 * @field: the field to access
10357 * Used to determine if a method is allowed to access the specified field.
10359 * Returns: TRUE if the given @method is allowed to access the @field while following
10360 * the accessibility rules of the CLI.
10363 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10365 /* FIXME: check all overlapping fields */
10366 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10368 MonoClass *nested = method->klass->nested_in;
10370 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10373 nested = nested->nested_in;
10380 * mono_method_can_access_method:
10381 * @method: Method that will attempt to access the other method
10382 * @called: the method that we want to probe for accessibility.
10384 * Used to determine if the @method is allowed to access the specified @called method.
10386 * Returns: TRUE if the given @method is allowed to invoke the @called while following
10387 * the accessibility rules of the CLI.
10390 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10392 int can = can_access_member (method->klass, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10394 MonoClass *nested = method->klass->nested_in;
10396 can = can_access_member (nested, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10399 nested = nested->nested_in;
10404 * with generics calls to explicit interface implementations can be expressed
10405 * directly: the method is private, but we must allow it. This may be opening
10406 * a hole or the generics code should handle this differently.
10407 * Maybe just ensure the interface type is public.
10409 if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
10415 * mono_method_can_access_method_full:
10416 * @method: The caller method
10417 * @called: The called method
10418 * @context_klass: The static type on stack of the owner @called object used
10420 * This function must be used with instance calls, as they have more strict family accessibility.
10421 * It can be used with static methods, but context_klass should be NULL.
10423 * Returns: TRUE if caller have proper visibility and acessibility to @called
10426 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10428 MonoClass *access_class = method->klass;
10429 MonoClass *member_class = called->klass;
10430 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10432 MonoClass *nested = access_class->nested_in;
10434 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10437 nested = nested->nested_in;
10444 can = can_access_type (access_class, member_class);
10446 MonoClass *nested = access_class->nested_in;
10448 can = can_access_type (nested, member_class);
10451 nested = nested->nested_in;
10458 if (called->is_inflated) {
10459 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10460 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10469 * mono_method_can_access_field_full:
10470 * @method: The caller method
10471 * @field: The accessed field
10472 * @context_klass: The static type on stack of the owner @field object used
10474 * This function must be used with instance fields, as they have more strict family accessibility.
10475 * It can be used with static fields, but context_klass should be NULL.
10477 * Returns: TRUE if caller have proper visibility and acessibility to @field
10480 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10482 MonoClass *access_class = method->klass;
10483 MonoClass *member_class = field->parent;
10484 /* FIXME: check all overlapping fields */
10485 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10487 MonoClass *nested = access_class->nested_in;
10489 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10492 nested = nested->nested_in;
10499 can = can_access_type (access_class, member_class);
10501 MonoClass *nested = access_class->nested_in;
10503 can = can_access_type (nested, member_class);
10506 nested = nested->nested_in;
10516 * mono_class_can_access_class:
10517 * @source_class: The source class
10518 * @target_class: The accessed class
10520 * This function returns is @target_class is visible to @source_class
10522 * Returns: TRUE if source have proper visibility and acessibility to target
10525 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10527 return can_access_type (source_class, target_class);
10531 * mono_type_is_valid_enum_basetype:
10532 * @type: The MonoType to check
10534 * Returns: TRUE if the type can be used as the basetype of an enum
10536 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10537 switch (type->type) {
10540 case MONO_TYPE_BOOLEAN:
10543 case MONO_TYPE_CHAR:
10557 * mono_class_is_valid_enum:
10558 * @klass: An enum class to be validated
10560 * This method verify the required properties an enum should have.
10562 * Returns: TRUE if the informed enum class is valid
10564 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10565 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10566 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10568 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10569 MonoClassField * field;
10570 gpointer iter = NULL;
10571 gboolean found_base_field = FALSE;
10573 g_assert (klass->enumtype);
10574 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10575 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10579 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10582 while ((field = mono_class_get_fields (klass, &iter))) {
10583 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10584 if (found_base_field)
10586 found_base_field = TRUE;
10587 if (!mono_type_is_valid_enum_basetype (field->type))
10592 if (!found_base_field)
10595 if (klass->method.count > 0)
10602 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10604 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10608 * mono_class_setup_interface_id:
10610 * Initializes MonoClass::interface_id if required.
10612 * LOCKING: Acquires the loader lock.
10615 mono_class_setup_interface_id (MonoClass *klass)
10617 mono_loader_lock ();
10618 if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10619 klass->interface_id = mono_get_unique_iid (klass);
10620 mono_loader_unlock ();
10624 * mono_class_alloc_ext:
10626 * Allocate klass->ext if not already done.
10629 mono_class_alloc_ext (MonoClass *klass)
10636 ext = (MonoClassExt *)mono_class_alloc0 (klass, sizeof (MonoClassExt));
10637 mono_image_lock (klass->image);
10638 mono_memory_barrier ();
10641 class_ext_size += sizeof (MonoClassExt);
10642 mono_image_unlock (klass->image);
10646 * mono_class_setup_interfaces:
10648 * Initialize klass->interfaces/interfaces_count.
10649 * LOCKING: Acquires the loader lock.
10650 * This function can fail the type.
10653 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10655 int i, interface_count;
10656 MonoClass **interfaces;
10658 mono_error_init (error);
10660 if (klass->interfaces_inited)
10663 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10664 MonoType *args [1];
10666 /* generic IList, ICollection, IEnumerable */
10667 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10668 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10670 args [0] = &klass->element_class->byval_arg;
10671 interfaces [0] = mono_class_bind_generic_parameters (
10672 mono_defaults.generic_ilist_class, 1, args, FALSE);
10673 if (interface_count > 1)
10674 interfaces [1] = mono_class_bind_generic_parameters (
10675 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10676 } else if (klass->generic_class) {
10677 MonoClass *gklass = klass->generic_class->container_class;
10679 mono_class_setup_interfaces (gklass, error);
10680 if (!mono_error_ok (error)) {
10681 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10685 interface_count = gklass->interface_count;
10686 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10687 for (i = 0; i < interface_count; i++) {
10688 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10689 if (!mono_error_ok (error)) {
10690 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10695 interface_count = 0;
10699 mono_image_lock (klass->image);
10701 if (!klass->interfaces_inited) {
10702 klass->interface_count = interface_count;
10703 klass->interfaces = interfaces;
10705 mono_memory_barrier ();
10707 klass->interfaces_inited = TRUE;
10710 mono_image_unlock (klass->image);
10714 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10716 MonoClass *klass = field->parent;
10717 MonoImage *image = klass->image;
10718 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10719 int field_idx = field - klass->fields;
10721 mono_error_init (error);
10724 MonoClassField *gfield = >d->fields [field_idx];
10725 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10726 if (!mono_error_ok (error)) {
10727 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10728 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10731 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10732 if (!mono_error_ok (error)) {
10733 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10734 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10738 guint32 cols [MONO_FIELD_SIZE];
10739 MonoGenericContainer *container = NULL;
10740 int idx = klass->field.first + field_idx;
10742 /*FIXME, in theory we do not lazy load SRE fields*/
10743 g_assert (!image_is_dynamic (image));
10745 if (klass->generic_container) {
10746 container = klass->generic_container;
10748 container = gtd->generic_container;
10749 g_assert (container);
10752 /* klass->field.first and idx points into the fieldptr table */
10753 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10755 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10756 mono_error_set_type_load_class (error, klass, "Could not verify field %s signature", field->name);;
10757 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
10761 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10763 mono_metadata_decode_value (sig, &sig);
10764 /* FIELD signature == 0x06 */
10765 g_assert (*sig == 0x06);
10767 field->type = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10768 if (!field->type) {
10769 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10770 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10776 mono_field_resolve_flags (MonoClassField *field)
10778 MonoClass *klass = field->parent;
10779 MonoImage *image = klass->image;
10780 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10781 int field_idx = field - klass->fields;
10785 MonoClassField *gfield = >d->fields [field_idx];
10786 return mono_field_get_flags (gfield);
10788 int idx = klass->field.first + field_idx;
10790 /*FIXME, in theory we do not lazy load SRE fields*/
10791 g_assert (!image_is_dynamic (image));
10793 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10798 * mono_class_setup_basic_field_info:
10799 * @class: The class to initialize
10801 * Initializes the klass->fields array of fields.
10802 * Aquires the loader lock.
10805 mono_class_setup_basic_field_info_locking (MonoClass *klass)
10807 mono_loader_lock ();
10808 mono_class_setup_basic_field_info (klass);
10809 mono_loader_unlock ();
10813 * mono_class_get_fields_lazy:
10814 * @klass: the MonoClass to act on
10816 * This routine is an iterator routine for retrieving the fields in a class.
10817 * Only minimal information about fields are loaded. Accessors must be used
10818 * for all MonoClassField returned.
10820 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10821 * iterate over all of the elements. When no more values are
10822 * available, the return value is NULL.
10824 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10827 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10829 MonoClassField* field;
10833 mono_class_setup_basic_field_info_locking (klass);
10834 if (!klass->fields)
10836 /* start from the first */
10837 if (klass->field.count) {
10838 *iter = &klass->fields [0];
10839 return (MonoClassField *)*iter;
10845 field = (MonoClassField *)*iter;
10847 if (field < &klass->fields [klass->field.count]) {
10849 return (MonoClassField *)*iter;
10855 mono_class_full_name (MonoClass *klass)
10857 return mono_type_full_name (&klass->byval_arg);
10860 /* Declare all shared lazy type lookup functions */
10861 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, System.Runtime.InteropServices, SafeHandle)