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);
909 if (!mono_error_ok (&error)) {
910 mono_error_cleanup (&error);
917 * mono_class_inflate_generic_type:
919 * @context: a generics context
920 * @error: error context to use
922 * If @type is a generic type and @context is not NULL, instantiate it using the
923 * generics context @context.
925 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
926 * on the heap and is owned by the caller.
929 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
931 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
935 * mono_class_inflate_generic_type_no_copy:
937 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
941 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
943 MonoType *inflated = NULL;
945 mono_error_init (error);
947 inflated = inflate_generic_type (image, type, context, error);
948 return_val_if_nok (error, NULL);
954 mono_stats.inflated_type_count++;
959 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
964 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
965 return_val_if_nok (error, NULL);
967 res = mono_class_from_mono_type (inflated);
968 mono_metadata_free_type (inflated);
973 * mono_class_inflate_generic_class:
975 * Inflate the class GKLASS with CONTEXT.
978 mono_class_inflate_generic_class (MonoClass *gklass, MonoGenericContext *context)
983 res = mono_class_inflate_generic_class_checked (gklass, context, &error);
984 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
991 static MonoGenericContext
992 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
994 MonoGenericInst *class_inst = NULL;
995 MonoGenericInst *method_inst = NULL;
996 MonoGenericContext res = { NULL, NULL };
998 mono_error_init (error);
1000 if (context->class_inst) {
1001 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
1002 if (!mono_error_ok (error))
1006 if (context->method_inst) {
1007 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
1008 if (!mono_error_ok (error))
1012 res.class_inst = class_inst;
1013 res.method_inst = method_inst;
1019 * mono_class_inflate_generic_method:
1020 * @method: a generic method
1021 * @context: a generics context
1023 * Instantiate the generic method @method using the generics context @context.
1025 * Returns: The new instantiated method
1028 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
1030 return mono_class_inflate_generic_method_full (method, NULL, context);
1034 mono_class_inflate_generic_method_checked (MonoMethod *method, MonoGenericContext *context, MonoError *error)
1036 return mono_class_inflate_generic_method_full_checked (method, NULL, context, error);
1040 * mono_class_inflate_generic_method_full:
1042 * Instantiate method @method with the generic context @context.
1043 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
1044 * Use mono_method_signature () and mono_method_get_header () to get the correct values.
1047 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
1050 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
1051 if (!mono_error_ok (&error))
1052 /*FIXME do proper error handling - on this case, kill this function. */
1053 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
1059 * mono_class_inflate_generic_method_full_checked:
1060 * Same as mono_class_inflate_generic_method_full but return failure using @error.
1063 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
1066 MonoMethodInflated *iresult, *cached;
1067 MonoMethodSignature *sig;
1068 MonoGenericContext tmp_context;
1070 mono_error_init (error);
1072 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1073 while (method->is_inflated) {
1074 MonoGenericContext *method_context = mono_method_get_context (method);
1075 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1077 tmp_context = inflate_generic_context (method_context, context, error);
1078 return_val_if_nok (error, NULL);
1080 context = &tmp_context;
1082 if (mono_metadata_generic_context_equal (method_context, context))
1085 method = imethod->declaring;
1089 * A method only needs to be inflated if the context has argument for which it is
1092 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1093 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1096 if (!((method->is_generic && context->method_inst) ||
1097 (method->klass->generic_container && context->class_inst)))
1100 iresult = g_new0 (MonoMethodInflated, 1);
1101 iresult->context = *context;
1102 iresult->declaring = method;
1104 if (!context->method_inst && method->is_generic)
1105 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1107 if (!context->class_inst) {
1108 g_assert (!iresult->declaring->klass->generic_class);
1109 if (iresult->declaring->klass->generic_container)
1110 iresult->context.class_inst = iresult->declaring->klass->generic_container->context.class_inst;
1111 else if (iresult->declaring->klass->generic_class)
1112 iresult->context.class_inst = iresult->declaring->klass->generic_class->context.class_inst;
1114 /* This can happen with some callers like mono_object_get_virtual_method () */
1115 if (!iresult->declaring->klass->generic_container && !iresult->declaring->klass->generic_class)
1116 iresult->context.class_inst = NULL;
1118 MonoImageSet *set = mono_metadata_get_image_set_for_method (iresult);
1121 mono_image_set_lock (set);
1122 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1123 mono_image_set_unlock (set);
1127 return (MonoMethod*)cached;
1130 mono_stats.inflated_method_count++;
1132 inflated_methods_size += sizeof (MonoMethodInflated);
1134 sig = mono_method_signature (method);
1136 char *name = mono_type_get_full_name (method->klass);
1137 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1143 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1145 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1148 result = (MonoMethod *) iresult;
1149 result->is_inflated = TRUE;
1150 result->is_generic = FALSE;
1151 result->sre_method = FALSE;
1152 result->signature = NULL;
1154 if (!context->method_inst) {
1155 /* Set the generic_container of the result to the generic_container of method */
1156 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1158 if (generic_container) {
1159 result->is_generic = 1;
1160 mono_method_set_generic_container (result, generic_container);
1164 if (!klass_hint || !klass_hint->generic_class ||
1165 klass_hint->generic_class->container_class != method->klass ||
1166 klass_hint->generic_class->context.class_inst != context->class_inst)
1169 if (method->klass->generic_container)
1170 result->klass = klass_hint;
1172 if (!result->klass) {
1173 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1174 if (!mono_error_ok (error))
1177 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1179 mono_metadata_free_type (inflated);
1183 * FIXME: This should hold, but it doesn't:
1185 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1186 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1187 * g_assert (result->is_generic);
1190 * Fixing this here causes other things to break, hence a very
1191 * ugly hack in mini-trampolines.c - see
1192 * is_generic_method_definition().
1196 mono_image_set_lock (set);
1197 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1199 g_hash_table_insert (set->gmethod_cache, iresult, iresult);
1200 iresult->owner = set;
1203 mono_image_set_unlock (set);
1205 return (MonoMethod*)cached;
1213 * mono_get_inflated_method:
1215 * Obsolete. We keep it around since it's mentioned in the public API.
1218 mono_get_inflated_method (MonoMethod *method)
1224 * mono_method_get_context_general:
1226 * @uninflated: handle uninflated methods?
1228 * Returns the generic context of a method or NULL if it doesn't have
1229 * one. For an inflated method that's the context stored in the
1230 * method. Otherwise it's in the method's generic container or in the
1231 * generic container of the method's class.
1234 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1236 if (method->is_inflated) {
1237 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1238 return &imethod->context;
1242 if (method->is_generic)
1243 return &(mono_method_get_generic_container (method)->context);
1244 if (method->klass->generic_container)
1245 return &method->klass->generic_container->context;
1250 * mono_method_get_context:
1253 * Returns the generic context for method if it's inflated, otherwise
1257 mono_method_get_context (MonoMethod *method)
1259 return mono_method_get_context_general (method, FALSE);
1263 * mono_method_get_generic_container:
1265 * Returns the generic container of METHOD, which should be a generic method definition.
1266 * Returns NULL if METHOD is not a generic method definition.
1267 * LOCKING: Acquires the loader lock.
1269 MonoGenericContainer*
1270 mono_method_get_generic_container (MonoMethod *method)
1272 MonoGenericContainer *container;
1274 if (!method->is_generic)
1277 container = (MonoGenericContainer *)mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1278 g_assert (container);
1284 * mono_method_set_generic_container:
1286 * Sets the generic container of METHOD to CONTAINER.
1287 * LOCKING: Acquires the image lock.
1290 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1292 g_assert (method->is_generic);
1294 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1298 * mono_class_find_enum_basetype:
1299 * @class: The enum class
1301 * Determine the basetype of an enum by iterating through its fields. We do this
1302 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1305 mono_class_find_enum_basetype (MonoClass *klass, MonoError *error)
1307 MonoGenericContainer *container = NULL;
1308 MonoImage *m = klass->image;
1309 const int top = klass->field.count;
1312 g_assert (klass->enumtype);
1314 mono_error_init (error);
1316 if (klass->generic_container)
1317 container = klass->generic_container;
1318 else if (klass->generic_class) {
1319 MonoClass *gklass = klass->generic_class->container_class;
1321 container = gklass->generic_container;
1322 g_assert (container);
1326 * Fetch all the field information.
1328 for (i = 0; i < top; i++){
1330 guint32 cols [MONO_FIELD_SIZE];
1331 int idx = klass->field.first + i;
1334 /* klass->field.first and idx points into the fieldptr table */
1335 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1337 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1340 if (!mono_verifier_verify_field_signature (klass->image, cols [MONO_FIELD_SIGNATURE], NULL)) {
1341 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x", cols [MONO_FIELD_SIGNATURE]);
1345 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1346 mono_metadata_decode_value (sig, &sig);
1347 /* FIELD signature == 0x06 */
1349 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig);
1353 ftype = mono_metadata_parse_type_checked (m, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
1357 if (klass->generic_class) {
1358 //FIXME do we leak here?
1359 ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (klass), error);
1360 if (!mono_error_ok (error))
1362 ftype->attrs = cols [MONO_FIELD_FLAGS];
1367 mono_error_set_type_load_class (error, klass, "Could not find base type");
1370 mono_loader_assert_no_error ();
1375 * Checks for MonoClass::exception_type without resolving all MonoType's into MonoClass'es
1378 mono_type_has_exceptions (MonoType *type)
1380 switch (type->type) {
1381 case MONO_TYPE_CLASS:
1382 case MONO_TYPE_VALUETYPE:
1383 case MONO_TYPE_SZARRAY:
1384 return mono_class_has_failure (type->data.klass);
1385 case MONO_TYPE_ARRAY:
1386 return mono_class_has_failure (type->data.array->eklass);
1387 case MONO_TYPE_GENERICINST:
1388 return mono_class_has_failure (mono_generic_class_get_class (type->data.generic_class));
1397 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1401 mono_class_alloc (MonoClass *klass, int size)
1403 if (klass->generic_class)
1404 return mono_image_set_alloc (klass->generic_class->owner, size);
1406 return mono_image_alloc (klass->image, size);
1410 mono_class_alloc0 (MonoClass *klass, int size)
1414 res = mono_class_alloc (klass, size);
1415 memset (res, 0, size);
1419 #define mono_class_new0(klass,struct_type, n_structs) \
1420 ((struct_type *) mono_class_alloc0 ((klass), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1423 * mono_class_setup_basic_field_info:
1424 * @class: The class to initialize
1426 * Initializes the klass->fields.
1427 * LOCKING: Assumes the loader lock is held.
1430 mono_class_setup_basic_field_info (MonoClass *klass)
1432 MonoClassField *field;
1440 gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
1441 image = klass->image;
1442 top = klass->field.count;
1444 if (klass->generic_class && image_is_dynamic (klass->generic_class->container_class->image) && !klass->generic_class->container_class->wastypebuilder) {
1446 * This happens when a generic instance of an unfinished generic typebuilder
1447 * is used as an element type for creating an array type. We can't initialize
1448 * the fields of this class using the fields of gklass, since gklass is not
1449 * finished yet, fields could be added to it later.
1455 mono_class_setup_basic_field_info (gtd);
1457 top = gtd->field.count;
1458 klass->field.first = gtd->field.first;
1459 klass->field.count = gtd->field.count;
1462 klass->fields = (MonoClassField *)mono_class_alloc0 (klass, sizeof (MonoClassField) * top);
1465 * Fetch all the field information.
1467 for (i = 0; i < top; i++){
1468 field = &klass->fields [i];
1469 field->parent = klass;
1472 field->name = mono_field_get_name (>d->fields [i]);
1474 int idx = klass->field.first + i;
1475 /* klass->field.first and idx points into the fieldptr table */
1476 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1477 /* The name is needed for fieldrefs */
1478 field->name = mono_metadata_string_heap (image, name_idx);
1484 * mono_class_setup_fields:
1485 * @class: The class to initialize
1487 * Initializes the klass->fields.
1488 * LOCKING: Assumes the loader lock is held.
1491 mono_class_setup_fields (MonoClass *klass)
1494 MonoImage *m = klass->image;
1496 guint32 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1497 int i, blittable = TRUE;
1498 guint32 real_size = 0;
1499 guint32 packing_size = 0;
1500 gboolean explicit_size;
1501 MonoClassField *field;
1502 MonoGenericContainer *container = NULL;
1503 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
1506 * FIXME: We have a race condition here. It's possible that this function returns
1507 * to its caller with `instance_size` set to `0` instead of the actual size. This
1508 * is not a problem when the function is called recursively on the same class,
1509 * because the size will be initialized by the outer invocation. What follows is a
1510 * description of how it can occur in other cases, too. There it is a problem,
1511 * because it can lead to the GC being asked to allocate an object of size `0`,
1512 * which SGen chokes on. The race condition is triggered infrequently by
1513 * `tests/sgen-suspend.cs`.
1515 * This function is called for a class whenever one of its subclasses is inited.
1516 * For example, it's called for every subclass of Object. What it does is this:
1518 * if (klass->setup_fields_called)
1521 * klass->instance_size = 0;
1523 * klass->setup_fields_called = 1;
1524 * ... critical point
1525 * klass->instance_size = actual_instance_size;
1527 * The last two steps are sometimes reversed, but that only changes the way in which
1528 * the race condition works.
1530 * Assume thread A goes through this function and makes it to the critical point.
1531 * Now thread B runs the function and, since `setup_fields_called` is set, returns
1532 * immediately, but `instance_size` is incorrect.
1534 * The other case looks like this:
1536 * if (klass->setup_fields_called)
1538 * ... critical point X
1539 * klass->instance_size = 0;
1540 * ... critical point Y
1541 * klass->instance_size = actual_instance_size;
1543 * klass->setup_fields_called = 1;
1545 * Assume thread A goes through the function and makes it to critical point X. Now
1546 * thread B runs through the whole of the function, returning, assuming
1547 * `instance_size` is set. At that point thread A gets to run and makes it to
1548 * critical point Y, at which time `instance_size` is `0` again, invalidating thread
1551 if (klass->setup_fields_called)
1554 if (klass->generic_class && image_is_dynamic (klass->generic_class->container_class->image) && !klass->generic_class->container_class->wastypebuilder) {
1556 * This happens when a generic instance of an unfinished generic typebuilder
1557 * is used as an element type for creating an array type. We can't initialize
1558 * the fields of this class using the fields of gklass, since gklass is not
1559 * finished yet, fields could be added to it later.
1564 mono_class_setup_basic_field_info (klass);
1565 top = klass->field.count;
1568 mono_class_setup_fields (gtd);
1569 if (mono_class_has_failure (gtd)) {
1570 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1575 klass->instance_size = 0;
1577 klass->sizes.class_size = 0;
1579 if (klass->parent) {
1580 /* For generic instances, klass->parent might not have been initialized */
1581 mono_class_init (klass->parent);
1582 if (!klass->parent->size_inited) {
1583 mono_class_setup_fields (klass->parent);
1584 if (mono_class_has_failure (klass->parent)) {
1585 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1589 klass->instance_size += klass->parent->instance_size;
1590 klass->min_align = klass->parent->min_align;
1591 /* we use |= since it may have been set already */
1592 klass->has_references |= klass->parent->has_references;
1593 blittable = klass->parent->blittable;
1595 klass->instance_size = sizeof (MonoObject);
1596 klass->min_align = 1;
1599 /* We can't really enable 16 bytes alignment until the GC supports it.
1600 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1601 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1602 Bug #506144 is an example of this issue.
1604 if (klass->simd_type)
1605 klass->min_align = 16;
1607 /* Get the real size */
1608 explicit_size = mono_metadata_packing_from_typedef (klass->image, klass->type_token, &packing_size, &real_size);
1610 if (explicit_size) {
1611 if ((packing_size & 0xffffff00) != 0) {
1612 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, packing_size);
1613 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
1616 klass->packing_size = packing_size;
1617 real_size += klass->instance_size;
1621 if (explicit_size && real_size) {
1622 klass->instance_size = MAX (real_size, klass->instance_size);
1624 klass->blittable = blittable;
1625 mono_memory_barrier ();
1626 klass->size_inited = 1;
1627 klass->fields_inited = 1;
1628 klass->setup_fields_called = 1;
1632 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(mono_is_corlib_image (klass->image) && !strcmp (klass->name_space, "System") && !strcmp (klass->name, "ValueType")))
1635 /* Prevent infinite loops if the class references itself */
1636 klass->setup_fields_called = 1;
1638 if (klass->generic_container) {
1639 container = klass->generic_container;
1641 container = gtd->generic_container;
1642 g_assert (container);
1646 * Fetch all the field information.
1648 for (i = 0; i < top; i++){
1649 int idx = klass->field.first + i;
1650 field = &klass->fields [i];
1652 field->parent = klass;
1655 mono_field_resolve_type (field, &error);
1656 if (!mono_error_ok (&error)) {
1657 /*mono_field_resolve_type already failed class*/
1658 mono_error_cleanup (&error);
1662 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(klass), field->name);
1663 g_assert (field->type);
1666 if (mono_field_is_deleted (field))
1669 MonoClassField *gfield = >d->fields [i];
1670 field->offset = gfield->offset;
1672 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1674 mono_metadata_field_info (m, idx, &offset, NULL, NULL);
1675 field->offset = offset;
1677 if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1678 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Missing field layout info for %s", field->name));
1681 if (field->offset < -1) { /*-1 is used to encode special static fields */
1682 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Invalid negative field offset %d for %s", field->offset, field->name));
1685 if (klass->generic_container) {
1686 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic class cannot have explicit layout."));
1692 /* Only do these checks if we still think this type is blittable */
1693 if (blittable && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1694 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1697 MonoClass *field_class = mono_class_from_mono_type (field->type);
1699 mono_class_setup_fields (field_class);
1700 if (mono_class_has_failure (field_class)) {
1701 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1705 if (!field_class || !field_class->blittable)
1710 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1711 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
1712 blittable = klass->element_class->blittable;
1715 if (mono_type_has_exceptions (field->type)) {
1716 char *class_name = mono_type_get_full_name (klass);
1717 char *type_name = mono_type_full_name (field->type);
1719 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1720 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1721 g_free (class_name);
1725 /* The def_value of fields is compute lazily during vtable creation */
1728 if (klass == mono_defaults.string_class)
1731 klass->blittable = blittable;
1733 if (klass->enumtype && !mono_class_enum_basetype (klass)) {
1734 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1737 if (explicit_size && real_size) {
1738 klass->instance_size = MAX (real_size, klass->instance_size);
1741 if (mono_class_has_failure (klass))
1743 mono_class_layout_fields (klass);
1745 /*valuetypes can't be neither bigger than 1Mb or empty. */
1746 if (klass->valuetype && (klass->instance_size <= 0 || klass->instance_size > (0x100000 + sizeof (MonoObject))))
1747 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1749 mono_memory_barrier ();
1750 klass->fields_inited = 1;
1754 * mono_class_setup_fields_locking:
1755 * @class: The class to initialize
1757 * Initializes the klass->fields array of fields.
1758 * Aquires the loader lock.
1761 mono_class_setup_fields_locking (MonoClass *klass)
1763 /* This can be checked without locks */
1764 if (klass->fields_inited)
1766 mono_loader_lock ();
1767 mono_class_setup_fields (klass);
1768 mono_loader_unlock ();
1772 * mono_class_has_references:
1774 * Returns whenever @klass->has_references is set, initializing it if needed.
1775 * Aquires the loader lock.
1778 mono_class_has_references (MonoClass *klass)
1780 if (klass->init_pending) {
1781 /* Be conservative */
1784 mono_class_init (klass);
1786 return klass->has_references;
1791 * mono_type_get_basic_type_from_generic:
1794 * Returns a closed type corresponding to the possibly open type
1798 mono_type_get_basic_type_from_generic (MonoType *type)
1800 /* When we do generic sharing we let type variables stand for reference/primitive types. */
1801 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) &&
1802 (!type->data.generic_param->gshared_constraint || type->data.generic_param->gshared_constraint->type == MONO_TYPE_OBJECT))
1803 return &mono_defaults.object_class->byval_arg;
1808 type_has_references (MonoClass *klass, MonoType *ftype)
1810 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)))))
1812 if (!ftype->byref && (ftype->type == MONO_TYPE_VAR || ftype->type == MONO_TYPE_MVAR)) {
1813 MonoGenericParam *gparam = ftype->data.generic_param;
1815 if (gparam->gshared_constraint)
1816 return mono_class_has_references (mono_class_from_mono_type (gparam->gshared_constraint));
1822 * mono_class_layout_fields:
1825 * Compute the placement of fields inside an object or struct, according to
1826 * the layout rules and set the following fields in @class:
1827 * - has_references (if the class contains instance references firled or structs that contain references)
1828 * - has_static_refs (same, but for static fields)
1829 * - instance_size (size of the object in memory)
1830 * - class_size (size needed for the static fields)
1831 * - size_inited (flag set when the instance_size is set)
1833 * LOCKING: this is supposed to be called with the loader lock held.
1836 mono_class_layout_fields (MonoClass *klass)
1839 const int top = klass->field.count;
1840 guint32 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1841 guint32 pass, passes, real_size;
1842 gboolean gc_aware_layout = FALSE;
1843 gboolean has_static_fields = FALSE;
1844 MonoClassField *field;
1847 * When we do generic sharing we need to have layout
1848 * information for open generic classes (either with a generic
1849 * context containing type variables or with a generic
1850 * container), so we don't return in that case anymore.
1854 * Enable GC aware auto layout: in this mode, reference
1855 * fields are grouped together inside objects, increasing collector
1857 * Requires that all classes whose layout is known to native code be annotated
1858 * with [StructLayout (LayoutKind.Sequential)]
1859 * Value types have gc_aware_layout disabled by default, as per
1860 * what the default is for other runtimes.
1862 /* corlib is missing [StructLayout] directives in many places */
1863 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1864 if (!klass->valuetype)
1865 gc_aware_layout = TRUE;
1868 /* Compute klass->has_references */
1870 * Process non-static fields first, since static fields might recursively
1871 * refer to the class itself.
1873 for (i = 0; i < top; i++) {
1876 field = &klass->fields [i];
1878 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1879 ftype = mono_type_get_underlying_type (field->type);
1880 ftype = mono_type_get_basic_type_from_generic (ftype);
1881 if (type_has_references (klass, ftype))
1882 klass->has_references = TRUE;
1886 for (i = 0; i < top; i++) {
1889 field = &klass->fields [i];
1891 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1892 ftype = mono_type_get_underlying_type (field->type);
1893 ftype = mono_type_get_basic_type_from_generic (ftype);
1894 if (type_has_references (klass, ftype))
1895 klass->has_static_refs = TRUE;
1899 for (i = 0; i < top; i++) {
1902 field = &klass->fields [i];
1904 ftype = mono_type_get_underlying_type (field->type);
1905 ftype = mono_type_get_basic_type_from_generic (ftype);
1906 if (type_has_references (klass, ftype)) {
1907 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1908 klass->has_static_refs = TRUE;
1910 klass->has_references = TRUE;
1915 * Compute field layout and total size (not considering static fields)
1919 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1920 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1922 if (gc_aware_layout)
1927 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1930 if (klass->parent) {
1931 mono_class_setup_fields (klass->parent);
1932 if (mono_class_has_failure (klass->parent)) {
1933 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1936 real_size = klass->parent->instance_size;
1938 real_size = sizeof (MonoObject);
1941 for (pass = 0; pass < passes; ++pass) {
1942 for (i = 0; i < top; i++){
1947 field = &klass->fields [i];
1949 if (mono_field_is_deleted (field))
1951 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1954 ftype = mono_type_get_underlying_type (field->type);
1955 ftype = mono_type_get_basic_type_from_generic (ftype);
1956 if (gc_aware_layout) {
1957 if (type_has_references (klass, ftype)) {
1966 if ((top == 1) && (klass->instance_size == sizeof (MonoObject)) &&
1967 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1968 /* This field is a hack inserted by MCS to empty structures */
1972 size = mono_type_size (field->type, &align);
1974 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1975 align = klass->packing_size ? MIN (klass->packing_size, align): align;
1976 /* if the field has managed references, we need to force-align it
1979 if (type_has_references (klass, ftype))
1980 align = MAX (align, sizeof (gpointer));
1982 klass->min_align = MAX (align, klass->min_align);
1983 field->offset = real_size;
1985 field->offset += align - 1;
1986 field->offset &= ~(align - 1);
1988 /*TypeBuilders produce all sort of weird things*/
1989 g_assert (image_is_dynamic (klass->image) || field->offset > 0);
1990 real_size = field->offset + size;
1993 klass->instance_size = MAX (real_size, klass->instance_size);
1995 if (klass->instance_size & (klass->min_align - 1)) {
1996 klass->instance_size += klass->min_align - 1;
1997 klass->instance_size &= ~(klass->min_align - 1);
2001 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
2005 for (i = 0; i < top; i++) {
2010 field = &klass->fields [i];
2013 * There must be info about all the fields in a type if it
2014 * uses explicit layout.
2016 if (mono_field_is_deleted (field))
2018 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2021 size = mono_type_size (field->type, &align);
2022 align = klass->packing_size ? MIN (klass->packing_size, align): align;
2023 klass->min_align = MAX (align, klass->min_align);
2026 * When we get here, field->offset is already set by the
2027 * loader (for either runtime fields or fields loaded from metadata).
2028 * The offset is from the start of the object: this works for both
2029 * classes and valuetypes.
2031 field->offset += sizeof (MonoObject);
2032 ftype = mono_type_get_underlying_type (field->type);
2033 ftype = mono_type_get_basic_type_from_generic (ftype);
2034 if (type_has_references (klass, ftype)) {
2035 if (field->offset % sizeof (gpointer)) {
2036 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
2043 real_size = MAX (real_size, size + field->offset);
2046 if (klass->has_references) {
2047 ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
2049 /* Check for overlapping reference and non-reference fields */
2050 for (i = 0; i < top; i++) {
2053 field = &klass->fields [i];
2055 if (mono_field_is_deleted (field))
2057 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2059 ftype = mono_type_get_underlying_type (field->type);
2060 if (MONO_TYPE_IS_REFERENCE (ftype))
2061 ref_bitmap [field->offset / sizeof (gpointer)] = 1;
2063 for (i = 0; i < top; i++) {
2064 field = &klass->fields [i];
2066 if (mono_field_is_deleted (field))
2068 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2071 // FIXME: Too much code does this
2073 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field->offset / sizeof (gpointer)]) {
2074 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);
2075 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
2079 g_free (ref_bitmap);
2082 klass->instance_size = MAX (real_size, klass->instance_size);
2083 if (klass->instance_size & (klass->min_align - 1)) {
2084 klass->instance_size += klass->min_align - 1;
2085 klass->instance_size &= ~(klass->min_align - 1);
2091 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2093 * This leads to all kinds of problems with nested structs, so only
2094 * enable it when a MONO_DEBUG property is set.
2096 * For small structs, set min_align to at least the struct size to improve
2097 * performance, and since the JIT memset/memcpy code assumes this and generates
2098 * unaligned accesses otherwise. See #78990 for a testcase.
2100 if (mono_align_small_structs) {
2101 if (klass->instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2102 klass->min_align = MAX (klass->min_align, klass->instance_size - sizeof (MonoObject));
2106 mono_memory_barrier ();
2107 klass->size_inited = 1;
2110 * Compute static field layout and size
2112 for (i = 0; i < top; i++){
2116 field = &klass->fields [i];
2118 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2120 if (mono_field_is_deleted (field))
2123 if (mono_type_has_exceptions (field->type)) {
2124 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
2128 has_static_fields = TRUE;
2130 size = mono_type_size (field->type, &align);
2131 field->offset = klass->sizes.class_size;
2132 /*align is always non-zero here*/
2133 field->offset += align - 1;
2134 field->offset &= ~(align - 1);
2135 klass->sizes.class_size = field->offset + size;
2138 if (has_static_fields && klass->sizes.class_size == 0)
2139 /* Simplify code which depends on class_size != 0 if the class has static fields */
2140 klass->sizes.class_size = 8;
2144 create_array_method (MonoClass *klass, const char *name, MonoMethodSignature *sig)
2148 method = (MonoMethod *) mono_image_alloc0 (klass->image, sizeof (MonoMethodPInvoke));
2149 method->klass = klass;
2150 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2151 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2152 method->signature = sig;
2153 method->name = name;
2156 if (name [0] == '.') {
2157 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2159 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2165 * mono_class_setup_methods:
2168 * Initializes the 'methods' array in CLASS.
2169 * Calling this method should be avoided if possible since it allocates a lot
2170 * of long-living MonoMethod structures.
2171 * Methods belonging to an interface are assigned a sequential slot starting
2174 * On failure this function sets klass->exception_type
2177 mono_class_setup_methods (MonoClass *klass)
2180 MonoMethod **methods;
2185 if (klass->generic_class) {
2187 MonoClass *gklass = klass->generic_class->container_class;
2189 mono_class_init (gklass);
2190 if (!mono_class_has_failure (gklass))
2191 mono_class_setup_methods (gklass);
2192 if (mono_class_has_failure (gklass)) {
2193 /* FIXME make exception_data less opaque so it's possible to dup it here */
2194 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2198 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2199 count = gklass->method.count;
2200 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * (count + 1));
2202 for (i = 0; i < count; i++) {
2203 methods [i] = mono_class_inflate_generic_method_full_checked (
2204 gklass->methods [i], klass, mono_class_get_context (klass), &error);
2205 if (!mono_error_ok (&error)) {
2206 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2207 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)));
2210 mono_error_cleanup (&error);
2214 } else if (klass->rank) {
2216 MonoMethod *amethod;
2217 MonoMethodSignature *sig;
2218 int count_generic = 0, first_generic = 0;
2220 gboolean jagged_ctor = FALSE;
2222 count = 3 + (klass->rank > 1? 2: 1);
2224 mono_class_setup_interfaces (klass, &error);
2225 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2227 if (klass->rank == 1 && klass->element_class->rank) {
2229 klass->method.count ++;
2232 if (klass->interface_count) {
2233 count_generic = generic_array_methods (klass);
2234 first_generic = count;
2235 count += klass->interface_count * count_generic;
2238 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * count);
2240 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2241 sig->ret = &mono_defaults.void_class->byval_arg;
2242 sig->pinvoke = TRUE;
2243 sig->hasthis = TRUE;
2244 for (i = 0; i < klass->rank; ++i)
2245 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2247 amethod = create_array_method (klass, ".ctor", sig);
2248 methods [method_num++] = amethod;
2249 if (klass->rank > 1) {
2250 sig = mono_metadata_signature_alloc (klass->image, klass->rank * 2);
2251 sig->ret = &mono_defaults.void_class->byval_arg;
2252 sig->pinvoke = TRUE;
2253 sig->hasthis = TRUE;
2254 for (i = 0; i < klass->rank * 2; ++i)
2255 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2257 amethod = create_array_method (klass, ".ctor", sig);
2258 methods [method_num++] = amethod;
2262 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2263 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2264 sig->ret = &mono_defaults.void_class->byval_arg;
2265 sig->pinvoke = TRUE;
2266 sig->hasthis = TRUE;
2267 for (i = 0; i < klass->rank + 1; ++i)
2268 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2269 amethod = create_array_method (klass, ".ctor", sig);
2270 methods [method_num++] = amethod;
2273 /* element Get (idx11, [idx2, ...]) */
2274 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2275 sig->ret = &klass->element_class->byval_arg;
2276 sig->pinvoke = TRUE;
2277 sig->hasthis = TRUE;
2278 for (i = 0; i < klass->rank; ++i)
2279 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2280 amethod = create_array_method (klass, "Get", sig);
2281 methods [method_num++] = amethod;
2282 /* element& Address (idx11, [idx2, ...]) */
2283 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2284 sig->ret = &klass->element_class->this_arg;
2285 sig->pinvoke = TRUE;
2286 sig->hasthis = TRUE;
2287 for (i = 0; i < klass->rank; ++i)
2288 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2289 amethod = create_array_method (klass, "Address", sig);
2290 methods [method_num++] = amethod;
2291 /* void Set (idx11, [idx2, ...], element) */
2292 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2293 sig->ret = &mono_defaults.void_class->byval_arg;
2294 sig->pinvoke = TRUE;
2295 sig->hasthis = TRUE;
2296 for (i = 0; i < klass->rank; ++i)
2297 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2298 sig->params [i] = &klass->element_class->byval_arg;
2299 amethod = create_array_method (klass, "Set", sig);
2300 methods [method_num++] = amethod;
2302 for (i = 0; i < klass->interface_count; i++)
2303 setup_generic_array_ifaces (klass, klass->interfaces [i], methods, first_generic + i * count_generic);
2307 count = klass->method.count;
2308 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * count);
2309 for (i = 0; i < count; ++i) {
2310 int idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_METHOD, klass->method.first + i + 1);
2311 methods [i] = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | idx, klass, NULL, &error);
2313 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)));
2314 mono_error_cleanup (&error);
2319 if (MONO_CLASS_IS_INTERFACE (klass)) {
2321 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2322 for (i = 0; i < count; ++i) {
2323 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2324 methods [i]->slot = slot++;
2328 mono_image_lock (klass->image);
2330 if (!klass->methods) {
2331 klass->method.count = count;
2333 /* Needed because of the double-checking locking pattern */
2334 mono_memory_barrier ();
2336 klass->methods = methods;
2339 mono_image_unlock (klass->image);
2343 * mono_class_get_method_by_index:
2345 * Returns klass->methods [index], initializing klass->methods if neccesary.
2347 * LOCKING: Acquires the loader lock.
2350 mono_class_get_method_by_index (MonoClass *klass, int index)
2353 /* Avoid calling setup_methods () if possible */
2354 if (klass->generic_class && !klass->methods) {
2355 MonoClass *gklass = klass->generic_class->container_class;
2358 m = mono_class_inflate_generic_method_full_checked (
2359 gklass->methods [index], klass, mono_class_get_context (klass), &error);
2360 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2362 * If setup_methods () is called later for this class, no duplicates are created,
2363 * since inflate_generic_method guarantees that only one instance of a method
2364 * is created for each context.
2367 mono_class_setup_methods (klass);
2368 g_assert (m == klass->methods [index]);
2372 mono_class_setup_methods (klass);
2373 if (mono_class_has_failure (klass)) /*FIXME do proper error handling*/
2375 g_assert (index >= 0 && index < klass->method.count);
2376 return klass->methods [index];
2381 * mono_class_get_inflated_method:
2383 * Given an inflated class CLASS and a method METHOD which should be a method of
2384 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2387 mono_class_get_inflated_method (MonoClass *klass, MonoMethod *method)
2389 MonoClass *gklass = klass->generic_class->container_class;
2392 g_assert (method->klass == gklass);
2394 mono_class_setup_methods (gklass);
2395 g_assert (!mono_class_has_failure (gklass)); /*FIXME do proper error handling*/
2397 for (i = 0; i < gklass->method.count; ++i) {
2398 if (gklass->methods [i] == method) {
2399 if (klass->methods) {
2400 return klass->methods [i];
2403 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], klass, mono_class_get_context (klass), &error);
2404 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2414 * mono_class_get_vtable_entry:
2416 * Returns klass->vtable [offset], computing it if neccesary. Returns NULL on failure.
2417 * LOCKING: Acquires the loader lock.
2420 mono_class_get_vtable_entry (MonoClass *klass, int offset)
2424 if (klass->rank == 1) {
2426 * szarrays do not overwrite any methods of Array, so we can avoid
2427 * initializing their vtables in some cases.
2429 mono_class_setup_vtable (klass->parent);
2430 if (offset < klass->parent->vtable_size)
2431 return klass->parent->vtable [offset];
2434 if (klass->generic_class) {
2436 MonoClass *gklass = klass->generic_class->container_class;
2437 mono_class_setup_vtable (gklass);
2438 m = gklass->vtable [offset];
2440 m = mono_class_inflate_generic_method_full_checked (m, klass, mono_class_get_context (klass), &error);
2441 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2443 mono_class_setup_vtable (klass);
2444 if (mono_class_has_failure (klass))
2446 m = klass->vtable [offset];
2453 * mono_class_get_vtable_size:
2455 * Return the vtable size for KLASS.
2458 mono_class_get_vtable_size (MonoClass *klass)
2460 mono_class_setup_vtable (klass);
2462 return klass->vtable_size;
2466 * mono_class_setup_properties:
2468 * Initialize klass->ext.property and klass->ext.properties.
2470 * This method can fail the class.
2473 mono_class_setup_properties (MonoClass *klass)
2475 guint startm, endm, i, j;
2476 guint32 cols [MONO_PROPERTY_SIZE];
2477 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2478 MonoProperty *properties;
2482 if (klass->ext && klass->ext->properties)
2485 if (klass->generic_class) {
2486 MonoClass *gklass = klass->generic_class->container_class;
2488 mono_class_init (gklass);
2489 mono_class_setup_properties (gklass);
2490 if (mono_class_has_failure (gklass)) {
2491 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2495 properties = mono_class_new0 (klass, MonoProperty, gklass->ext->property.count + 1);
2497 for (i = 0; i < gklass->ext->property.count; i++) {
2499 MonoProperty *prop = &properties [i];
2501 *prop = gklass->ext->properties [i];
2504 prop->get = mono_class_inflate_generic_method_full_checked (
2505 prop->get, klass, mono_class_get_context (klass), &error);
2507 prop->set = mono_class_inflate_generic_method_full_checked (
2508 prop->set, klass, mono_class_get_context (klass), &error);
2510 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2511 prop->parent = klass;
2514 first = gklass->ext->property.first;
2515 count = gklass->ext->property.count;
2517 first = mono_metadata_properties_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2518 count = last - first;
2521 mono_class_setup_methods (klass);
2522 if (mono_class_has_failure (klass))
2526 properties = (MonoProperty *)mono_class_alloc0 (klass, sizeof (MonoProperty) * count);
2527 for (i = first; i < last; ++i) {
2528 mono_metadata_decode_table_row (klass->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2529 properties [i - first].parent = klass;
2530 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2531 properties [i - first].name = mono_metadata_string_heap (klass->image, cols [MONO_PROPERTY_NAME]);
2533 startm = mono_metadata_methods_from_property (klass->image, i, &endm);
2534 for (j = startm; j < endm; ++j) {
2537 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2539 if (klass->image->uncompressed_metadata) {
2541 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2542 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2543 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2545 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - klass->method.first];
2548 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2549 case METHOD_SEMANTIC_SETTER:
2550 properties [i - first].set = method;
2552 case METHOD_SEMANTIC_GETTER:
2553 properties [i - first].get = method;
2562 mono_class_alloc_ext (klass);
2564 mono_image_lock (klass->image);
2566 if (klass->ext->properties) {
2567 /* We leak 'properties' which was allocated from the image mempool */
2568 mono_image_unlock (klass->image);
2572 klass->ext->property.first = first;
2573 klass->ext->property.count = count;
2575 /* Flush any pending writes as we do double checked locking on klass->ext->properties */
2576 mono_memory_barrier ();
2578 /* Leave this assignment as the last op in the function */
2579 klass->ext->properties = properties;
2581 mono_image_unlock (klass->image);
2585 inflate_method_listz (MonoMethod **methods, MonoClass *klass, MonoGenericContext *context)
2587 MonoMethod **om, **retval;
2590 for (om = methods, count = 0; *om; ++om, ++count)
2593 retval = g_new0 (MonoMethod*, count + 1);
2595 for (om = methods, count = 0; *om; ++om, ++count) {
2597 retval [count] = mono_class_inflate_generic_method_full_checked (*om, klass, context, &error);
2598 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2604 /*This method can fail the class.*/
2606 mono_class_setup_events (MonoClass *klass)
2609 guint startm, endm, i, j;
2610 guint32 cols [MONO_EVENT_SIZE];
2611 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2615 if (klass->ext && klass->ext->events)
2618 if (klass->generic_class) {
2619 MonoClass *gklass = klass->generic_class->container_class;
2620 MonoGenericContext *context = NULL;
2622 mono_class_setup_events (gklass);
2623 if (mono_class_has_failure (gklass)) {
2624 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2628 first = gklass->ext->event.first;
2629 count = gklass->ext->event.count;
2631 events = mono_class_new0 (klass, MonoEvent, count);
2634 context = mono_class_get_context (klass);
2636 for (i = 0; i < count; i++) {
2638 MonoEvent *event = &events [i];
2639 MonoEvent *gevent = &gklass->ext->events [i];
2641 mono_error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2643 event->parent = klass;
2644 event->name = gevent->name;
2645 event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, klass, context, &error) : NULL;
2646 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2647 event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, klass, context, &error) : NULL;
2648 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2649 event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, klass, context, &error) : NULL;
2650 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2652 #ifndef MONO_SMALL_CONFIG
2653 event->other = gevent->other ? inflate_method_listz (gevent->other, klass, context) : NULL;
2655 event->attrs = gevent->attrs;
2658 first = mono_metadata_events_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2659 count = last - first;
2662 mono_class_setup_methods (klass);
2663 if (mono_class_has_failure (klass)) {
2664 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2669 events = (MonoEvent *)mono_class_alloc0 (klass, sizeof (MonoEvent) * count);
2670 for (i = first; i < last; ++i) {
2671 MonoEvent *event = &events [i - first];
2673 mono_metadata_decode_table_row (klass->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2674 event->parent = klass;
2675 event->attrs = cols [MONO_EVENT_FLAGS];
2676 event->name = mono_metadata_string_heap (klass->image, cols [MONO_EVENT_NAME]);
2678 startm = mono_metadata_methods_from_event (klass->image, i, &endm);
2679 for (j = startm; j < endm; ++j) {
2682 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2684 if (klass->image->uncompressed_metadata) {
2686 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2687 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2688 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2690 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - klass->method.first];
2693 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2694 case METHOD_SEMANTIC_ADD_ON:
2695 event->add = method;
2697 case METHOD_SEMANTIC_REMOVE_ON:
2698 event->remove = method;
2700 case METHOD_SEMANTIC_FIRE:
2701 event->raise = method;
2703 case METHOD_SEMANTIC_OTHER: {
2704 #ifndef MONO_SMALL_CONFIG
2707 if (event->other == NULL) {
2708 event->other = g_new0 (MonoMethod*, 2);
2710 while (event->other [n])
2712 event->other = (MonoMethod **)g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2714 event->other [n] = method;
2715 /* NULL terminated */
2716 event->other [n + 1] = NULL;
2727 mono_class_alloc_ext (klass);
2729 mono_image_lock (klass->image);
2731 if (klass->ext->events) {
2732 mono_image_unlock (klass->image);
2736 klass->ext->event.first = first;
2737 klass->ext->event.count = count;
2739 /* Flush any pending writes as we do double checked locking on klass->ext.events */
2740 mono_memory_barrier ();
2742 /* Leave this assignment as the last op in the function */
2743 klass->ext->events = events;
2745 mono_image_unlock (klass->image);
2749 * Global pool of interface IDs, represented as a bitset.
2750 * LOCKING: Protected by the classes lock.
2752 static MonoBitSet *global_interface_bitset = NULL;
2755 * mono_unload_interface_ids:
2756 * @bitset: bit set of interface IDs
2758 * When an image is unloaded, the interface IDs associated with
2759 * the image are put back in the global pool of IDs so the numbers
2763 mono_unload_interface_ids (MonoBitSet *bitset)
2766 mono_bitset_sub (global_interface_bitset, bitset);
2771 mono_unload_interface_id (MonoClass *klass)
2773 if (global_interface_bitset && klass->interface_id) {
2775 mono_bitset_clear (global_interface_bitset, klass->interface_id);
2781 * mono_get_unique_iid:
2784 * Assign a unique integer ID to the interface represented by @class.
2785 * The ID will positive and as small as possible.
2786 * LOCKING: Acquires the classes lock.
2787 * Returns: The new ID.
2790 mono_get_unique_iid (MonoClass *klass)
2794 g_assert (MONO_CLASS_IS_INTERFACE (klass));
2798 if (!global_interface_bitset) {
2799 global_interface_bitset = mono_bitset_new (128, 0);
2802 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2804 int old_size = mono_bitset_size (global_interface_bitset);
2805 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2806 mono_bitset_free (global_interface_bitset);
2807 global_interface_bitset = new_set;
2810 mono_bitset_set (global_interface_bitset, iid);
2811 /* set the bit also in the per-image set */
2812 if (!klass->generic_class) {
2813 if (klass->image->interface_bitset) {
2814 if (iid >= mono_bitset_size (klass->image->interface_bitset)) {
2815 MonoBitSet *new_set = mono_bitset_clone (klass->image->interface_bitset, iid + 1);
2816 mono_bitset_free (klass->image->interface_bitset);
2817 klass->image->interface_bitset = new_set;
2820 klass->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2822 mono_bitset_set (klass->image->interface_bitset, iid);
2827 #ifndef MONO_SMALL_CONFIG
2828 if (mono_print_vtable) {
2830 char *type_name = mono_type_full_name (&klass->byval_arg);
2831 if (klass->generic_class && !klass->generic_class->context.class_inst->is_open) {
2832 generic_id = klass->generic_class->context.class_inst->id;
2833 g_assert (generic_id != 0);
2837 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, klass->image->name, type_name, generic_id);
2842 g_assert (iid <= 65535);
2847 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2852 mono_class_setup_interfaces (klass, error);
2853 return_if_nok (error);
2855 for (i = 0; i < klass->interface_count; i++) {
2856 ic = klass->interfaces [i];
2859 *res = g_ptr_array_new ();
2860 g_ptr_array_add (*res, ic);
2861 mono_class_init (ic);
2862 if (mono_class_has_failure (ic)) {
2863 mono_error_set_type_load_class (error, ic, "Error Loading class");
2867 collect_implemented_interfaces_aux (ic, res, error);
2868 return_if_nok (error);
2873 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2875 GPtrArray *res = NULL;
2877 collect_implemented_interfaces_aux (klass, &res, error);
2878 if (!mono_error_ok (error)) {
2880 g_ptr_array_free (res, TRUE);
2887 compare_interface_ids (const void *p_key, const void *p_element) {
2888 const MonoClass *key = (const MonoClass *)p_key;
2889 const MonoClass *element = *(const MonoClass **)p_element;
2891 return (key->interface_id - element->interface_id);
2894 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2896 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2897 MonoClass **result = (MonoClass **)mono_binary_search (
2899 klass->interfaces_packed,
2900 klass->interface_offsets_count,
2901 sizeof (MonoClass *),
2902 compare_interface_ids);
2904 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2911 * mono_class_interface_offset_with_variance:
2913 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2914 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2916 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2918 * FIXME figure out MS disambiguation rules and fix this function.
2921 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2922 int i = mono_class_interface_offset (klass, itf);
2923 *non_exact_match = FALSE;
2927 if (!mono_class_has_variant_generic_params (itf))
2930 for (i = 0; i < klass->interface_offsets_count; i++) {
2931 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2932 *non_exact_match = TRUE;
2933 return klass->interface_offsets_packed [i];
2941 print_implemented_interfaces (MonoClass *klass) {
2944 GPtrArray *ifaces = NULL;
2946 int ancestor_level = 0;
2948 name = mono_type_get_full_name (klass);
2949 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2952 for (i = 0; i < klass->interface_offsets_count; i++)
2953 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2954 klass->interfaces_packed [i]->interface_id,
2955 klass->interface_offsets_packed [i],
2956 klass->interfaces_packed [i]->method.count,
2957 klass->interfaces_packed [i]->name_space,
2958 klass->interfaces_packed [i]->name );
2959 printf ("Interface flags: ");
2960 for (i = 0; i <= klass->max_interface_id; i++)
2961 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2962 printf ("(%d,T)", i);
2964 printf ("(%d,F)", i);
2966 printf ("Dump interface flags:");
2967 #ifdef COMPRESSED_INTERFACE_BITMAP
2969 const uint8_t* p = klass->interface_bitmap;
2970 i = klass->max_interface_id;
2972 printf (" %d x 00 %02X", p [0], p [1]);
2978 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
2979 printf (" %02X", klass->interface_bitmap [i]);
2982 while (klass != NULL) {
2983 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
2984 ifaces = mono_class_get_implemented_interfaces (klass, &error);
2985 if (!mono_error_ok (&error)) {
2986 printf (" Type failed due to %s\n", mono_error_get_message (&error));
2987 mono_error_cleanup (&error);
2988 } else if (ifaces) {
2989 for (i = 0; i < ifaces->len; i++) {
2990 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
2991 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
2992 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2994 mono_class_interface_offset (klass, ic),
2999 g_ptr_array_free (ifaces, TRUE);
3002 klass = klass->parent;
3007 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
3010 args [0] = &arg0->byval_arg;
3012 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
3016 array_class_get_if_rank (MonoClass *klass, guint rank)
3018 return rank ? mono_array_class_get (klass, rank) : klass;
3022 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
3024 valuetype_types [0] = eclass;
3025 if (eclass == mono_defaults.int16_class)
3026 valuetype_types [1] = mono_defaults.uint16_class;
3027 else if (eclass == mono_defaults.uint16_class)
3028 valuetype_types [1] = mono_defaults.int16_class;
3029 else if (eclass == mono_defaults.int32_class)
3030 valuetype_types [1] = mono_defaults.uint32_class;
3031 else if (eclass == mono_defaults.uint32_class)
3032 valuetype_types [1] = mono_defaults.int32_class;
3033 else if (eclass == mono_defaults.int64_class)
3034 valuetype_types [1] = mono_defaults.uint64_class;
3035 else if (eclass == mono_defaults.uint64_class)
3036 valuetype_types [1] = mono_defaults.int64_class;
3037 else if (eclass == mono_defaults.byte_class)
3038 valuetype_types [1] = mono_defaults.sbyte_class;
3039 else if (eclass == mono_defaults.sbyte_class)
3040 valuetype_types [1] = mono_defaults.byte_class;
3041 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
3042 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
3045 /* this won't be needed once bug #325495 is completely fixed
3046 * though we'll need something similar to know which interfaces to allow
3047 * in arrays when they'll be lazyly created
3049 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
3050 * MS returns diferrent types based on which instance is called. For example:
3051 * object obj = new byte[10][];
3052 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
3053 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
3056 * Fixing this should kill quite some code, save some bits and improve compatibility.
3059 get_implicit_generic_array_interfaces (MonoClass *klass, int *num, int *is_enumerator)
3061 MonoClass *eclass = klass->element_class;
3062 static MonoClass* generic_icollection_class = NULL;
3063 static MonoClass* generic_ienumerable_class = NULL;
3064 static MonoClass* generic_ienumerator_class = NULL;
3065 static MonoClass* generic_ireadonlylist_class = NULL;
3066 static MonoClass* generic_ireadonlycollection_class = NULL;
3067 MonoClass *valuetype_types[2] = { NULL, NULL };
3068 MonoClass **interfaces = NULL;
3069 int i, nifaces, interface_count, real_count, original_rank;
3071 gboolean internal_enumerator;
3072 gboolean eclass_is_valuetype;
3074 if (!mono_defaults.generic_ilist_class) {
3078 internal_enumerator = FALSE;
3079 eclass_is_valuetype = FALSE;
3080 original_rank = eclass->rank;
3081 if (klass->byval_arg.type != MONO_TYPE_SZARRAY) {
3082 if (klass->generic_class && klass->nested_in == mono_defaults.array_class && strcmp (klass->name, "InternalEnumerator`1") == 0) {
3084 * For a Enumerator<T[]> we need to get the list of interfaces for T.
3086 eclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
3087 original_rank = eclass->rank;
3089 eclass = eclass->element_class;
3090 internal_enumerator = TRUE;
3091 *is_enumerator = TRUE;
3099 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
3100 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
3102 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
3104 if (!generic_icollection_class) {
3105 generic_icollection_class = mono_class_load_from_name (mono_defaults.corlib,
3106 "System.Collections.Generic", "ICollection`1");
3107 generic_ienumerable_class = mono_class_load_from_name (mono_defaults.corlib,
3108 "System.Collections.Generic", "IEnumerable`1");
3109 generic_ienumerator_class = mono_class_load_from_name (mono_defaults.corlib,
3110 "System.Collections.Generic", "IEnumerator`1");
3111 generic_ireadonlylist_class = mono_class_load_from_name (mono_defaults.corlib,
3112 "System.Collections.Generic", "IReadOnlyList`1");
3113 generic_ireadonlycollection_class = mono_class_load_from_name (mono_defaults.corlib,
3114 "System.Collections.Generic", "IReadOnlyCollection`1");
3117 mono_class_init (eclass);
3120 * Arrays in 2.0 need to implement a number of generic interfaces
3121 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
3122 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
3123 * We collect the types needed to build the
3124 * instantiations in interfaces at intervals of 3/5, because 3/5 are
3125 * the generic interfaces needed to implement.
3127 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
3128 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
3130 if (eclass->valuetype) {
3131 nifaces = generic_ireadonlylist_class ? 5 : 3;
3132 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
3134 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
3135 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
3136 if (internal_enumerator) {
3138 if (valuetype_types [1])
3142 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3143 interfaces [0] = valuetype_types [0];
3144 if (valuetype_types [1])
3145 interfaces [nifaces] = valuetype_types [1];
3147 eclass_is_valuetype = TRUE;
3150 int idepth = eclass->idepth;
3151 if (!internal_enumerator)
3153 nifaces = generic_ireadonlylist_class ? 2 : 3;
3155 // FIXME: This doesn't seem to work/required for generic params
3156 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
3157 mono_class_setup_interface_offsets (eclass);
3159 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
3160 /* we add object for interfaces and the supertypes for the other
3161 * types. The last of the supertypes is the element class itself which we
3162 * already created the explicit interfaces for (so we include it for IEnumerator
3163 * and exclude it for arrays).
3165 if (MONO_CLASS_IS_INTERFACE (eclass))
3168 interface_count += idepth;
3169 if (eclass->rank && eclass->element_class->valuetype) {
3170 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3171 if (valuetype_types [1])
3174 /* IList, ICollection, IEnumerable, IReadOnlyList */
3175 interface_count *= nifaces;
3176 real_count = interface_count;
3177 if (internal_enumerator) {
3178 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3179 if (valuetype_types [1])
3182 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3183 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3184 interfaces [0] = mono_defaults.object_class;
3188 for (i = 0; i < idepth; i++) {
3189 mono_class_init (eclass->supertypes [i]);
3190 interfaces [j] = eclass->supertypes [i];
3194 if (all_interfaces) {
3195 for (i = 0; i < eclass->interface_offsets_count; i++) {
3196 interfaces [j] = eclass->interfaces_packed [i];
3200 for (i = 0; i < eclass->interface_count; i++) {
3201 interfaces [j] = eclass->interfaces [i];
3205 if (valuetype_types [1]) {
3206 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3211 /* instantiate the generic interfaces */
3212 for (i = 0; i < interface_count; i += nifaces) {
3213 MonoClass *iface = interfaces [i];
3215 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3216 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3218 if (eclass->valuetype) {
3219 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3220 if (generic_ireadonlylist_class) {
3221 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3222 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3225 if (!generic_ireadonlylist_class)
3226 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3229 if (internal_enumerator) {
3231 /* instantiate IEnumerator<iface> */
3232 for (i = 0; i < interface_count; i++) {
3233 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3235 j = interface_count;
3236 if (!eclass_is_valuetype) {
3237 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3238 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3241 for (i = 0; i < eclass->idepth; i++) {
3242 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3246 for (i = 0; i < eclass->interface_offsets_count; i++) {
3247 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3251 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3253 if (valuetype_types [1])
3254 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3258 char *type_name = mono_type_get_name_full (&klass->byval_arg, 0);
3259 for (i = 0; i < real_count; ++i) {
3260 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3261 g_print ("%s implements %s\n", type_name, name);
3272 find_array_interface (MonoClass *klass, const char *name)
3275 for (i = 0; i < klass->interface_count; ++i) {
3276 if (strcmp (klass->interfaces [i]->name, name) == 0)
3283 * Return the number of virtual methods.
3284 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3285 * Return -1 on failure.
3286 * FIXME It would be nice if this information could be cached somewhere.
3289 count_virtual_methods (MonoClass *klass)
3293 klass = mono_class_get_generic_type_definition (klass); /*We can find this information by looking at the GTD*/
3295 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
3296 mono_class_setup_methods (klass);
3297 if (mono_class_has_failure (klass))
3300 for (i = 0; i < klass->method.count; ++i) {
3301 flags = klass->methods [i]->flags;
3302 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3306 for (i = 0; i < klass->method.count; ++i) {
3307 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
3309 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3317 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3325 m = (l + num_ifaces) / 2;
3326 if (interfaces_full [m] == ic)
3328 if (l == num_ifaces)
3330 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3339 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3341 int i = find_interface (num_ifaces, interfaces_full, ic);
3343 return interface_offsets_full [i];
3348 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3350 int i = find_interface (num_ifaces, interfaces_full, ic);
3354 interface_offsets_full [i] = offset;
3357 for (i = 0; i < num_ifaces; ++i) {
3358 if (interfaces_full [i]) {
3360 if (interfaces_full [i]->interface_id < ic->interface_id)
3363 while (end < num_ifaces && interfaces_full [end]) end++;
3364 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3365 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3367 interfaces_full [i] = ic;
3368 interface_offsets_full [i] = offset;
3374 #ifdef COMPRESSED_INTERFACE_BITMAP
3377 * Compressed interface bitmap design.
3379 * Interface bitmaps take a large amount of memory, because their size is
3380 * linear with the maximum interface id assigned in the process (each interface
3381 * is assigned a unique id as it is loaded). The number of interface classes
3382 * is high because of the many implicit interfaces implemented by arrays (we'll
3383 * need to lazy-load them in the future).
3384 * Most classes implement a very small number of interfaces, so the bitmap is
3385 * sparse. This bitmap needs to be checked by interface casts, so access to the
3386 * needed bit must be fast and doable with few jit instructions.
3388 * The current compression format is as follows:
3389 * *) it is a sequence of one or more two-byte elements
3390 * *) the first byte in the element is the count of empty bitmap bytes
3391 * at the current bitmap position
3392 * *) the second byte in the element is an actual bitmap byte at the current
3395 * As an example, the following compressed bitmap bytes:
3396 * 0x07 0x01 0x00 0x7
3397 * correspond to the following bitmap:
3398 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3400 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3401 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3402 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3406 * mono_compress_bitmap:
3407 * @dest: destination buffer
3408 * @bitmap: bitmap buffer
3409 * @size: size of @bitmap in bytes
3411 * This is a mono internal function.
3412 * The @bitmap data is compressed into a format that is small but
3413 * still searchable in few instructions by the JIT and runtime.
3414 * The compressed data is stored in the buffer pointed to by the
3415 * @dest array. Passing a #NULL value for @dest allows to just compute
3416 * the size of the buffer.
3417 * This compression algorithm assumes the bits set in the bitmap are
3418 * few and far between, like in interface bitmaps.
3419 * Returns: The size of the compressed bitmap in bytes.
3422 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3426 const uint8_t *end = bitmap + size;
3427 while (bitmap < end) {
3428 if (*bitmap || numz == 255) {
3452 * mono_class_interface_match:
3453 * @bitmap: a compressed bitmap buffer
3454 * @id: the index to check in the bitmap
3456 * This is a mono internal function.
3457 * Checks if a bit is set in a compressed interface bitmap. @id must
3458 * be already checked for being smaller than the maximum id encoded in the
3461 * Returns: A non-zero value if bit @id is set in the bitmap @bitmap,
3465 mono_class_interface_match (const uint8_t *bitmap, int id)
3468 id -= bitmap [0] * 8;
3472 return bitmap [1] & (1 << id);
3481 * LOCKING: this is supposed to be called with the loader lock held.
3482 * Return -1 on failure and set exception_type
3485 setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite)
3489 int i, j, max_iid, num_ifaces;
3490 MonoClass **interfaces_full = NULL;
3491 int *interface_offsets_full = NULL;
3493 GPtrArray **ifaces_array = NULL;
3494 int interface_offsets_count;
3495 MonoClass **array_interfaces = NULL;
3496 int num_array_interfaces;
3497 int is_enumerator = FALSE;
3499 mono_class_setup_supertypes (klass);
3501 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3502 * implicit interfaces have the property that they are assigned the same slot in the
3503 * vtables for compatible interfaces
3505 array_interfaces = get_implicit_generic_array_interfaces (klass, &num_array_interfaces, &is_enumerator);
3507 /* compute maximum number of slots and maximum interface id */
3509 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3510 ifaces_array = g_new0 (GPtrArray *, klass->idepth);
3511 for (j = 0; j < klass->idepth; j++) {
3512 k = klass->supertypes [j];
3513 num_ifaces += k->interface_count;
3514 for (i = 0; i < k->interface_count; i++) {
3515 ic = k->interfaces [i];
3518 mono_class_init (ic);
3520 if (max_iid < ic->interface_id)
3521 max_iid = ic->interface_id;
3523 ifaces = mono_class_get_implemented_interfaces (k, &error);
3524 if (!mono_error_ok (&error)) {
3525 char *name = mono_type_get_full_name (k);
3526 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)));
3528 mono_error_cleanup (&error);
3533 num_ifaces += ifaces->len;
3534 for (i = 0; i < ifaces->len; ++i) {
3535 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3536 if (max_iid < ic->interface_id)
3537 max_iid = ic->interface_id;
3539 ifaces_array [j] = ifaces;
3543 for (i = 0; i < num_array_interfaces; ++i) {
3544 ic = array_interfaces [i];
3545 mono_class_init (ic);
3546 if (max_iid < ic->interface_id)
3547 max_iid = ic->interface_id;
3550 if (MONO_CLASS_IS_INTERFACE (klass)) {
3552 if (max_iid < klass->interface_id)
3553 max_iid = klass->interface_id;
3555 klass->max_interface_id = max_iid;
3556 /* compute vtable offset for interfaces */
3557 interfaces_full = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3558 interface_offsets_full = (int *)g_malloc (sizeof (int) * num_ifaces);
3560 for (i = 0; i < num_ifaces; i++) {
3561 interface_offsets_full [i] = -1;
3564 /* skip the current class */
3565 for (j = 0; j < klass->idepth - 1; j++) {
3566 k = klass->supertypes [j];
3567 ifaces = ifaces_array [j];
3570 for (i = 0; i < ifaces->len; ++i) {
3572 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3574 /*Force the sharing of interface offsets between parent and subtypes.*/
3575 io = mono_class_interface_offset (k, ic);
3577 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3582 g_assert (klass == klass->supertypes [klass->idepth - 1]);
3583 ifaces = ifaces_array [klass->idepth - 1];
3585 for (i = 0; i < ifaces->len; ++i) {
3587 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3588 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3590 count = count_virtual_methods (ic);
3592 char *name = mono_type_get_full_name (ic);
3593 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error calculating interface offset of %s", name));
3602 if (MONO_CLASS_IS_INTERFACE (klass))
3603 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, klass, cur_slot, TRUE);
3605 if (num_array_interfaces) {
3606 if (is_enumerator) {
3607 int ienumerator_idx = find_array_interface (klass, "IEnumerator`1");
3608 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ienumerator_idx]);
3609 g_assert (ienumerator_offset >= 0);
3610 for (i = 0; i < num_array_interfaces; ++i) {
3611 ic = array_interfaces [i];
3612 if (strcmp (ic->name, "IEnumerator`1") == 0)
3613 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3615 g_assert_not_reached ();
3616 /*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);*/
3619 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3620 int ilist_iface_idx = find_array_interface (klass, "IList`1");
3621 MonoClass* ilist_class = klass->interfaces [ilist_iface_idx];
3622 int ireadonlylist_iface_idx = find_array_interface (klass, "IReadOnlyList`1");
3623 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? klass->interfaces [ireadonlylist_iface_idx] : NULL;
3624 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3625 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3626 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3627 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ilist_iface_idx]);
3628 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3629 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3630 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ireadonlylist_iface_idx]) : -1;
3631 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3632 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3633 for (i = 0; i < num_array_interfaces; ++i) {
3635 ic = array_interfaces [i];
3636 if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
3637 offset = ilist_offset;
3638 else if (strcmp (ic->name, "ICollection`1") == 0)
3639 offset = icollection_offset;
3640 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3641 offset = ienumerable_offset;
3642 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3643 offset = ireadonlylist_offset;
3644 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3645 offset = ireadonlycollection_offset;
3647 g_assert_not_reached ();
3648 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3649 /*g_print ("type %s has %s offset at %d (%s)\n", klass->name, ic->name, offset, klass->interfaces [0]->name);*/
3654 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3655 if (interface_offsets_full [i] != -1) {
3656 interface_offsets_count ++;
3661 * We might get called multiple times:
3662 * - mono_class_init ()
3663 * - mono_class_setup_vtable ().
3664 * - mono_class_setup_interface_offsets ().
3665 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3666 * means we have to overwrite those when called from other places (#4440).
3668 if (klass->interfaces_packed) {
3670 g_assert (klass->interface_offsets_count == interface_offsets_count);
3674 klass->interface_offsets_count = interface_offsets_count;
3675 klass->interfaces_packed = (MonoClass **)mono_class_alloc (klass, sizeof (MonoClass*) * interface_offsets_count);
3676 klass->interface_offsets_packed = (guint16 *)mono_class_alloc (klass, sizeof (guint16) * interface_offsets_count);
3677 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3678 #ifdef COMPRESSED_INTERFACE_BITMAP
3679 bitmap = g_malloc0 (bsize);
3681 bitmap = (uint8_t *)mono_class_alloc0 (klass, bsize);
3683 for (i = 0; i < interface_offsets_count; i++) {
3684 int id = interfaces_full [i]->interface_id;
3685 bitmap [id >> 3] |= (1 << (id & 7));
3686 klass->interfaces_packed [i] = interfaces_full [i];
3687 klass->interface_offsets_packed [i] = interface_offsets_full [i];
3688 /*if (num_array_interfaces)
3689 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]);*/
3691 #ifdef COMPRESSED_INTERFACE_BITMAP
3692 i = mono_compress_bitmap (NULL, bitmap, bsize);
3693 klass->interface_bitmap = mono_class_alloc0 (klass, i);
3694 mono_compress_bitmap (klass->interface_bitmap, bitmap, bsize);
3697 klass->interface_bitmap = bitmap;
3702 g_free (interfaces_full);
3703 g_free (interface_offsets_full);
3704 g_free (array_interfaces);
3705 for (i = 0; i < klass->idepth; i++) {
3706 ifaces = ifaces_array [i];
3708 g_ptr_array_free (ifaces, TRUE);
3710 g_free (ifaces_array);
3712 //printf ("JUST DONE: ");
3713 //print_implemented_interfaces (klass);
3719 * Setup interface offsets for interfaces.
3721 * - klass->max_interface_id
3722 * - klass->interface_offsets_count
3723 * - klass->interfaces_packed
3724 * - klass->interface_offsets_packed
3725 * - klass->interface_bitmap
3727 * This function can fail @class.
3730 mono_class_setup_interface_offsets (MonoClass *klass)
3732 mono_loader_lock ();
3734 setup_interface_offsets (klass, 0, FALSE);
3736 mono_loader_unlock ();
3739 /*Checks if @klass has @parent as one of it's parents type gtd
3743 * Bar<T> : Foo<Bar<Bar<T>>>
3747 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3749 klass = mono_class_get_generic_type_definition (klass);
3750 parent = mono_class_get_generic_type_definition (parent);
3751 mono_class_setup_supertypes (klass);
3752 mono_class_setup_supertypes (parent);
3754 return klass->idepth >= parent->idepth &&
3755 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3759 mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup)
3761 MonoGenericInst *ginst;
3763 if (!klass->generic_class) {
3764 mono_class_setup_vtable_full (klass, in_setup);
3765 return !mono_class_has_failure (klass);
3768 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup);
3769 if (mono_class_has_failure (klass->generic_class->container_class)) {
3770 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to load generic definition vtable"));
3774 ginst = klass->generic_class->context.class_inst;
3775 for (i = 0; i < ginst->type_argc; ++i) {
3777 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3779 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3780 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3781 if (mono_class_has_gtd_parent (klass, arg) || mono_class_has_gtd_parent (arg, klass))
3783 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3784 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Failed to load generic parameter %d", i));
3792 * mono_class_setup_vtable:
3794 * Creates the generic vtable of CLASS.
3795 * Initializes the following fields in MonoClass:
3798 * Plus all the fields initialized by setup_interface_offsets ().
3799 * If there is an error during vtable construction, klass->exception_type is set.
3801 * LOCKING: Acquires the loader lock.
3804 mono_class_setup_vtable (MonoClass *klass)
3806 mono_class_setup_vtable_full (klass, NULL);
3810 mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
3812 MonoMethod **overrides;
3813 MonoGenericContext *context;
3821 if (MONO_CLASS_IS_INTERFACE (klass)) {
3822 /* This sets method->slot for all methods if this is an interface */
3823 mono_class_setup_methods (klass);
3827 if (mono_class_has_failure (klass))
3830 if (g_list_find (in_setup, klass))
3833 mono_loader_lock ();
3835 if (klass->vtable) {
3836 mono_loader_unlock ();
3840 mono_stats.generic_vtable_count ++;
3841 in_setup = g_list_prepend (in_setup, klass);
3843 if (klass->generic_class) {
3844 if (!mono_class_check_vtable_constraints (klass, in_setup)) {
3845 mono_loader_unlock ();
3846 g_list_remove (in_setup, klass);
3850 context = mono_class_get_context (klass);
3851 type_token = klass->generic_class->container_class->type_token;
3853 context = (MonoGenericContext *) klass->generic_container;
3854 type_token = klass->type_token;
3857 if (image_is_dynamic (klass->image)) {
3858 /* Generic instances can have zero method overrides without causing any harm.
3859 * This is true since we don't do layout all over again for them, we simply inflate
3860 * the layout of the parent.
3862 mono_reflection_get_dynamic_overrides (klass, &overrides, &onum);
3864 /* The following call fails if there are missing methods in the type */
3865 /* FIXME it's probably a good idea to avoid this for generic instances. */
3866 ok = mono_class_get_overrides_full (klass->image, type_token, &overrides, &onum, context);
3870 mono_class_setup_vtable_general (klass, overrides, onum, in_setup);
3872 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load list of method overrides"));
3876 mono_loader_unlock ();
3877 g_list_remove (in_setup, klass);
3882 #define DEBUG_INTERFACE_VTABLE_CODE 0
3883 #define TRACE_INTERFACE_VTABLE_CODE 0
3884 #define VERIFY_INTERFACE_VTABLE_CODE 0
3885 #define VTABLE_SELECTOR (1)
3887 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3888 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3889 if (!(VTABLE_SELECTOR)) break; \
3893 #define DEBUG_INTERFACE_VTABLE(stmt)
3896 #if TRACE_INTERFACE_VTABLE_CODE
3897 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3898 if (!(VTABLE_SELECTOR)) break; \
3902 #define TRACE_INTERFACE_VTABLE(stmt)
3905 #if VERIFY_INTERFACE_VTABLE_CODE
3906 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3907 if (!(VTABLE_SELECTOR)) break; \
3911 #define VERIFY_INTERFACE_VTABLE(stmt)
3915 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3917 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3921 GString *res = g_string_new ("");
3923 g_string_append_c (res, '(');
3924 for (i = 0; i < sig->param_count; ++i) {
3926 g_string_append_c (res, ',');
3927 mono_type_get_desc (res, sig->params [i], include_namespace);
3929 g_string_append (res, ")=>");
3930 if (sig->ret != NULL) {
3931 mono_type_get_desc (res, sig->ret, include_namespace);
3933 g_string_append (res, "NULL");
3936 g_string_free (res, FALSE);
3940 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3941 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3942 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3943 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3951 is_wcf_hack_disabled (void)
3953 static gboolean disabled;
3954 static gboolean inited = FALSE;
3956 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3963 check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
3965 MonoMethodSignature *cmsig, *imsig;
3966 if (strcmp (im->name, cm->name) == 0) {
3967 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3968 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3971 if (! slot_is_empty) {
3972 if (require_newslot) {
3973 if (! interface_is_explicitly_implemented_by_class) {
3974 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3977 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3978 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3982 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3985 cmsig = mono_method_signature (cm);
3986 imsig = mono_method_signature (im);
3987 if (!cmsig || !imsig) {
3988 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3992 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3993 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3994 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3995 TRACE_INTERFACE_VTABLE (printf ("]"));
3998 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3999 if (mono_security_core_clr_enabled ())
4000 mono_security_core_clr_check_override (klass, cm, im);
4002 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
4003 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4004 char *body_name = mono_method_full_name (cm, TRUE);
4005 char *decl_name = mono_method_full_name (im, TRUE);
4006 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));
4014 MonoClass *ic = im->klass;
4015 const char *ic_name_space = ic->name_space;
4016 const char *ic_name = ic->name;
4019 if (! require_newslot) {
4020 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
4023 if (cm->klass->rank == 0) {
4024 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
4027 cmsig = mono_method_signature (cm);
4028 imsig = mono_method_signature (im);
4029 if (!cmsig || !imsig) {
4030 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
4034 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4035 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
4036 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4037 TRACE_INTERFACE_VTABLE (printf ("]"));
4040 if (mono_class_get_image (ic) != mono_defaults.corlib) {
4041 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
4044 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
4045 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
4048 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))) {
4049 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
4053 subname = strstr (cm->name, ic_name_space);
4054 if (subname != cm->name) {
4055 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
4058 subname += strlen (ic_name_space);
4059 if (subname [0] != '.') {
4060 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
4064 if (strstr (subname, ic_name) != subname) {
4065 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
4068 subname += strlen (ic_name);
4069 if (subname [0] != '.') {
4070 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
4074 if (strcmp (subname, im->name) != 0) {
4075 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
4079 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
4080 if (mono_security_core_clr_enabled ())
4081 mono_security_core_clr_check_override (klass, cm, im);
4083 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
4084 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4085 char *body_name = mono_method_full_name (cm, TRUE);
4086 char *decl_name = mono_method_full_name (im, TRUE);
4087 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));
4097 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
4099 foreach_override (gpointer key, gpointer value, gpointer user_data) {
4100 MonoMethod *method = key;
4101 MonoMethod *override = value;
4102 MonoClass *method_class = mono_method_get_class (method);
4103 MonoClass *override_class = mono_method_get_class (override);
4105 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
4106 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
4107 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
4110 print_overrides (GHashTable *override_map, const char *message) {
4112 printf ("Override map \"%s\" START:\n", message);
4113 g_hash_table_foreach (override_map, foreach_override, NULL);
4114 printf ("Override map \"%s\" END.\n", message);
4116 printf ("Override map \"%s\" EMPTY.\n", message);
4120 print_vtable_full (MonoClass *klass, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
4121 char *full_name = mono_type_full_name (&klass->byval_arg);
4125 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
4127 if (print_interfaces) {
4128 print_implemented_interfaces (klass);
4129 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
4132 if (klass->parent) {
4133 parent_size = klass->parent->vtable_size;
4137 for (i = 0; i < size; ++i) {
4138 MonoMethod *cm = vtable [i];
4139 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
4140 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
4142 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
4150 #if VERIFY_INTERFACE_VTABLE_CODE
4152 mono_method_try_get_vtable_index (MonoMethod *method)
4154 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4155 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4156 if (imethod->declaring->is_generic)
4157 return imethod->declaring->slot;
4159 return method->slot;
4163 mono_class_verify_vtable (MonoClass *klass)
4166 char *full_name = mono_type_full_name (&klass->byval_arg);
4168 printf ("*** Verifying VTable of class '%s' \n", full_name);
4172 if (!klass->methods)
4175 for (i = 0; i < klass->method.count; ++i) {
4176 MonoMethod *cm = klass->methods [i];
4179 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4183 full_name = mono_method_full_name (cm, TRUE);
4185 slot = mono_method_try_get_vtable_index (cm);
4187 if (slot >= klass->vtable_size) {
4188 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, klass->vtable_size);
4192 if (slot >= 0 && klass->vtable [slot] != cm && (klass->vtable [slot])) {
4193 char *other_name = klass->vtable [slot] ? mono_method_full_name (klass->vtable [slot], TRUE) : g_strdup ("[null value]");
4194 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4195 g_free (other_name);
4198 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4205 print_unimplemented_interface_method_info (MonoClass *klass, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4207 char *method_signature;
4210 for (index = 0; index < onum; ++index) {
4211 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4212 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4214 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4215 type_name = mono_type_full_name (&klass->byval_arg);
4216 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4217 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4218 g_free (method_signature);
4220 mono_class_setup_methods (klass);
4221 if (mono_class_has_failure (klass)) {
4222 char *name = mono_type_get_full_name (klass);
4223 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4227 for (index = 0; index < klass->method.count; ++index) {
4228 MonoMethod *cm = klass->methods [index];
4229 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4231 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4232 g_free (method_signature);
4237 mono_method_get_method_definition (MonoMethod *method)
4239 while (method->is_inflated)
4240 method = ((MonoMethodInflated*)method)->declaring;
4245 verify_class_overrides (MonoClass *klass, MonoMethod **overrides, int onum)
4249 for (i = 0; i < onum; ++i) {
4250 MonoMethod *decl = overrides [i * 2];
4251 MonoMethod *body = overrides [i * 2 + 1];
4253 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (klass)) {
4254 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method belongs to a different class than the declared one"));
4258 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4259 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4260 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must not be static to override a base type"));
4262 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must be virtual to override a base type"));
4266 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4267 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4268 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a static method in a base type"));
4270 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a non virtual method in a base type"));
4274 if (!mono_class_is_assignable_from_slow (decl->klass, klass)) {
4275 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"));
4279 body = mono_method_get_method_definition (body);
4280 decl = mono_method_get_method_definition (decl);
4282 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4283 char *body_name = mono_method_full_name (body, TRUE);
4284 char *decl_name = mono_method_full_name (decl, TRUE);
4285 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));
4295 mono_class_need_stelemref_method (MonoClass *klass)
4297 return klass->rank == 1 && MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg);
4301 * LOCKING: this is supposed to be called with the loader lock held.
4304 mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int onum, GList *in_setup)
4308 MonoMethod **vtable;
4309 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4310 GPtrArray *ifaces = NULL;
4311 GHashTable *override_map = NULL;
4313 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4314 int first_non_interface_slot;
4316 GSList *virt_methods = NULL, *l;
4317 int stelemref_slot = 0;
4322 if (overrides && !verify_class_overrides (klass, overrides, onum))
4325 ifaces = mono_class_get_implemented_interfaces (klass, &error);
4326 if (!mono_error_ok (&error)) {
4327 char *name = mono_type_get_full_name (klass);
4328 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)));
4330 mono_error_cleanup (&error);
4332 } else if (ifaces) {
4333 for (i = 0; i < ifaces->len; i++) {
4334 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
4335 max_vtsize += ic->method.count;
4337 g_ptr_array_free (ifaces, TRUE);
4341 if (klass->parent) {
4342 mono_class_init (klass->parent);
4343 mono_class_setup_vtable_full (klass->parent, in_setup);
4345 if (mono_class_has_failure (klass->parent)) {
4346 char *name = mono_type_get_full_name (klass->parent);
4347 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Parent %s failed to load", name));
4352 max_vtsize += klass->parent->vtable_size;
4353 cur_slot = klass->parent->vtable_size;
4356 max_vtsize += klass->method.count;
4358 /*Array have a slot for stelemref*/
4359 if (mono_class_need_stelemref_method (klass)) {
4360 stelemref_slot = cur_slot;
4365 vtable = (MonoMethod **)alloca (sizeof (gpointer) * max_vtsize);
4366 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4368 /* printf ("METAINIT %s.%s\n", klass->name_space, klass->name); */
4370 cur_slot = setup_interface_offsets (klass, cur_slot, TRUE);
4371 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4374 max_iid = klass->max_interface_id;
4375 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4377 /* Optimized version for generic instances */
4378 if (klass->generic_class) {
4380 MonoClass *gklass = klass->generic_class->container_class;
4383 mono_class_setup_vtable_full (gklass, in_setup);
4384 if (mono_class_has_failure (gklass)) {
4385 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
4389 tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * gklass->vtable_size);
4390 klass->vtable_size = gklass->vtable_size;
4391 for (i = 0; i < gklass->vtable_size; ++i)
4392 if (gklass->vtable [i]) {
4393 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], klass, mono_class_get_context (klass), &error);
4394 if (!mono_error_ok (&error)) {
4395 char *err_msg = g_strdup_printf ("Could not inflate method due to %s", mono_error_get_message (&error));
4396 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
4398 mono_error_cleanup (&error);
4402 tmp [i]->slot = gklass->vtable [i]->slot;
4404 mono_memory_barrier ();
4405 klass->vtable = tmp;
4407 /* Have to set method->slot for abstract virtual methods */
4408 if (klass->methods && gklass->methods) {
4409 for (i = 0; i < klass->method.count; ++i)
4410 if (klass->methods [i]->slot == -1)
4411 klass->methods [i]->slot = gklass->methods [i]->slot;
4417 if (klass->parent && klass->parent->vtable_size) {
4418 MonoClass *parent = klass->parent;
4421 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4423 // Also inherit parent interface vtables, just as a starting point.
4424 // This is needed otherwise bug-77127.exe fails when the property methods
4425 // have different names in the iterface and the class, because for child
4426 // classes the ".override" information is not used anymore.
4427 for (i = 0; i < parent->interface_offsets_count; i++) {
4428 MonoClass *parent_interface = parent->interfaces_packed [i];
4429 int interface_offset = mono_class_interface_offset (klass, parent_interface);
4430 /*FIXME this is now dead code as this condition will never hold true.
4431 Since interface offsets are inherited then the offset of an interface implemented
4432 by a parent will never be the out of it's vtable boundary.
4434 if (interface_offset >= parent->vtable_size) {
4435 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4438 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4439 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4440 for (j = 0; j < parent_interface->method.count && !mono_class_has_failure (klass); j++) {
4441 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4442 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4443 parent_interface_offset + j, parent_interface_offset, j,
4444 interface_offset + j, interface_offset, j));
4451 /*Array have a slot for stelemref*/
4452 if (mono_class_need_stelemref_method (klass)) {
4453 MonoMethod *method = mono_marshal_get_virtual_stelemref (klass);
4455 method->slot = stelemref_slot;
4457 g_assert (method->slot == stelemref_slot);
4459 vtable [stelemref_slot] = method;
4462 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4463 /* override interface methods */
4464 for (i = 0; i < onum; i++) {
4465 MonoMethod *decl = overrides [i*2];
4466 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4468 dslot = mono_method_get_vtable_slot (decl);
4470 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
4474 dslot += mono_class_interface_offset (klass, decl->klass);
4475 vtable [dslot] = overrides [i*2 + 1];
4476 vtable [dslot]->slot = dslot;
4478 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4480 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4482 if (mono_security_core_clr_enabled ())
4483 mono_security_core_clr_check_override (klass, vtable [dslot], decl);
4486 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4487 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4490 * Create a list of virtual methods to avoid calling
4491 * mono_class_get_virtual_methods () which is slow because of the metadata
4495 gpointer iter = NULL;
4498 virt_methods = NULL;
4499 while ((cm = mono_class_get_virtual_methods (klass, &iter))) {
4500 virt_methods = g_slist_prepend (virt_methods, cm);
4502 if (mono_class_has_failure (klass))
4506 // Loop on all implemented interfaces...
4507 for (i = 0; i < klass->interface_offsets_count; i++) {
4508 MonoClass *parent = klass->parent;
4510 gboolean interface_is_explicitly_implemented_by_class;
4513 ic = klass->interfaces_packed [i];
4514 ic_offset = mono_class_interface_offset (klass, ic);
4516 mono_class_setup_methods (ic);
4517 if (mono_class_has_failure (ic))
4520 // Check if this interface is explicitly implemented (instead of just inherited)
4521 if (parent != NULL) {
4522 int implemented_interfaces_index;
4523 interface_is_explicitly_implemented_by_class = FALSE;
4524 for (implemented_interfaces_index = 0; implemented_interfaces_index < klass->interface_count; implemented_interfaces_index++) {
4525 if (ic == klass->interfaces [implemented_interfaces_index]) {
4526 interface_is_explicitly_implemented_by_class = TRUE;
4531 interface_is_explicitly_implemented_by_class = TRUE;
4534 // Loop on all interface methods...
4535 for (im_index = 0; im_index < ic->method.count; im_index++) {
4536 MonoMethod *im = ic->methods [im_index];
4537 int im_slot = ic_offset + im->slot;
4538 MonoMethod *override_im = (override_map != NULL) ? (MonoMethod *)g_hash_table_lookup (override_map, im) : NULL;
4540 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4543 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4545 // If there is an explicit implementation, just use it right away,
4546 // otherwise look for a matching method
4547 if (override_im == NULL) {
4551 // First look for a suitable method among the class methods
4552 for (l = virt_methods; l; l = l->next) {
4553 cm = (MonoMethod *)l->data;
4554 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)));
4555 if (check_interface_method_override (klass, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
4556 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4557 vtable [im_slot] = cm;
4558 /* Why do we need this? */
4563 TRACE_INTERFACE_VTABLE (printf ("\n"));
4564 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4568 // If the slot is still empty, look in all the inherited virtual methods...
4569 if ((vtable [im_slot] == NULL) && klass->parent != NULL) {
4570 MonoClass *parent = klass->parent;
4571 // Reverse order, so that last added methods are preferred
4572 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4573 MonoMethod *cm = parent->vtable [cm_index];
4575 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));
4576 if ((cm != NULL) && check_interface_method_override (klass, im, cm, FALSE, FALSE, TRUE)) {
4577 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4578 vtable [im_slot] = cm;
4579 /* Why do we need this? */
4585 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4587 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4591 g_assert (vtable [im_slot] == override_im);
4596 // If the class is not abstract, check that all its interface slots are full.
4597 // The check is done here and not directly at the end of the loop above because
4598 // it can happen (for injected generic array interfaces) that the same slot is
4599 // processed multiple times (those interfaces have overlapping slots), and it
4600 // will not always be the first pass the one that fills the slot.
4601 if (! (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4602 for (i = 0; i < klass->interface_offsets_count; i++) {
4606 ic = klass->interfaces_packed [i];
4607 ic_offset = mono_class_interface_offset (klass, ic);
4609 for (im_index = 0; im_index < ic->method.count; im_index++) {
4610 MonoMethod *im = ic->methods [im_index];
4611 int im_slot = ic_offset + im->slot;
4613 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4616 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4617 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4618 if (vtable [im_slot] == NULL) {
4619 print_unimplemented_interface_method_info (klass, ic, im, im_slot, overrides, onum);
4626 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4627 for (l = virt_methods; l; l = l->next) {
4628 cm = (MonoMethod *)l->data;
4630 * If the method is REUSE_SLOT, we must check in the
4631 * base class for a method to override.
4633 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4635 for (k = klass->parent; k ; k = k->parent) {
4640 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4641 MonoMethodSignature *cmsig, *m1sig;
4643 cmsig = mono_method_signature (cm);
4644 m1sig = mono_method_signature (m1);
4646 if (!cmsig || !m1sig) {
4647 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
4651 if (!strcmp(cm->name, m1->name) &&
4652 mono_metadata_signature_equal (cmsig, m1sig)) {
4654 if (mono_security_core_clr_enabled ())
4655 mono_security_core_clr_check_override (klass, cm, m1);
4657 slot = mono_method_get_vtable_slot (m1);
4661 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4662 char *body_name = mono_method_full_name (cm, TRUE);
4663 char *decl_name = mono_method_full_name (m1, TRUE);
4664 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));
4670 g_assert (cm->slot < max_vtsize);
4672 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4673 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4674 mono_method_full_name (m1, 1), m1,
4675 mono_method_full_name (cm, 1), cm));
4676 g_hash_table_insert (override_map, m1, cm);
4680 if (mono_class_has_failure (k))
4690 /*Non final newslot methods must be given a non-interface vtable slot*/
4691 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4695 cm->slot = cur_slot++;
4697 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4698 vtable [cm->slot] = cm;
4701 /* override non interface methods */
4702 for (i = 0; i < onum; i++) {
4703 MonoMethod *decl = overrides [i*2];
4704 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4705 g_assert (decl->slot != -1);
4706 vtable [decl->slot] = overrides [i*2 + 1];
4707 overrides [i * 2 + 1]->slot = decl->slot;
4709 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4710 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4711 mono_method_full_name (decl, 1), decl,
4712 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4713 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4715 if (mono_security_core_clr_enabled ())
4716 mono_security_core_clr_check_override (klass, vtable [decl->slot], decl);
4721 * If a method occupies more than one place in the vtable, and it is
4722 * overriden, then change the other occurances too.
4727 for (i = 0; i < max_vtsize; ++i)
4729 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4731 cm = (MonoMethod *)g_hash_table_lookup (override_map, vtable [i]);
4736 g_hash_table_destroy (override_map);
4737 override_map = NULL;
4740 g_slist_free (virt_methods);
4741 virt_methods = NULL;
4743 /* Ensure that all vtable slots are filled with concrete instance methods */
4744 if (!(klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4745 for (i = 0; i < cur_slot; ++i) {
4746 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4747 char *type_name = mono_type_get_full_name (klass);
4748 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4749 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));
4751 g_free (method_name);
4757 if (klass->generic_class) {
4758 MonoClass *gklass = klass->generic_class->container_class;
4760 mono_class_init (gklass);
4762 klass->vtable_size = MAX (gklass->vtable_size, cur_slot);
4764 /* Check that the vtable_size value computed in mono_class_init () is correct */
4765 if (klass->vtable_size)
4766 g_assert (cur_slot == klass->vtable_size);
4767 klass->vtable_size = cur_slot;
4770 /* Try to share the vtable with our parent. */
4771 if (klass->parent && (klass->parent->vtable_size == klass->vtable_size) && (memcmp (klass->parent->vtable, vtable, sizeof (gpointer) * klass->vtable_size) == 0)) {
4772 mono_memory_barrier ();
4773 klass->vtable = klass->parent->vtable;
4775 MonoMethod **tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * klass->vtable_size);
4776 memcpy (tmp, vtable, sizeof (gpointer) * klass->vtable_size);
4777 mono_memory_barrier ();
4778 klass->vtable = tmp;
4781 DEBUG_INTERFACE_VTABLE (print_vtable_full (klass, klass->vtable, klass->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4782 if (mono_print_vtable) {
4785 print_implemented_interfaces (klass);
4787 for (i = 0; i <= max_iid; i++)
4788 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
4791 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&klass->byval_arg),
4792 klass->vtable_size, icount);
4794 for (i = 0; i < cur_slot; ++i) {
4799 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4800 mono_method_full_name (cm, TRUE));
4806 printf ("Interfaces %s.%s (max_iid = %d)\n", klass->name_space,
4807 klass->name, max_iid);
4809 for (i = 0; i < klass->interface_count; i++) {
4810 ic = klass->interfaces [i];
4811 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4812 mono_class_interface_offset (klass, ic),
4813 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4816 for (k = klass->parent; k ; k = k->parent) {
4817 for (i = 0; i < k->interface_count; i++) {
4818 ic = k->interfaces [i];
4819 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4820 mono_class_interface_offset (klass, ic),
4821 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4827 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (klass));
4832 char *name = mono_type_get_full_name (klass);
4833 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("VTable setup of type %s failed", name));
4836 g_hash_table_destroy (override_map);
4838 g_slist_free (virt_methods);
4843 * mono_method_get_vtable_slot:
4845 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4846 * LOCKING: Acquires the loader lock.
4848 * FIXME Use proper MonoError machinery here.
4851 mono_method_get_vtable_slot (MonoMethod *method)
4853 if (method->slot == -1) {
4854 mono_class_setup_vtable (method->klass);
4855 if (mono_class_has_failure (method->klass))
4857 if (method->slot == -1) {
4861 if (!method->klass->generic_class) {
4862 g_assert (method->is_inflated);
4863 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4866 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4867 g_assert (method->klass->generic_class);
4868 gklass = method->klass->generic_class->container_class;
4869 mono_class_setup_methods (method->klass);
4870 g_assert (method->klass->methods);
4871 for (i = 0; i < method->klass->method.count; ++i) {
4872 if (method->klass->methods [i] == method)
4875 g_assert (i < method->klass->method.count);
4876 g_assert (gklass->methods);
4877 method->slot = gklass->methods [i]->slot;
4879 g_assert (method->slot != -1);
4881 return method->slot;
4885 * mono_method_get_vtable_index:
4888 * Returns the index into the runtime vtable to access the method or,
4889 * in the case of a virtual generic method, the virtual generic method
4890 * thunk. Returns -1 on failure.
4892 * FIXME Use proper MonoError machinery here.
4895 mono_method_get_vtable_index (MonoMethod *method)
4897 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4898 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4899 if (imethod->declaring->is_generic)
4900 return mono_method_get_vtable_slot (imethod->declaring);
4902 return mono_method_get_vtable_slot (method);
4905 static MonoMethod *default_ghc = NULL;
4906 static MonoMethod *default_finalize = NULL;
4907 static int finalize_slot = -1;
4908 static int ghc_slot = -1;
4911 initialize_object_slots (MonoClass *klass)
4916 if (klass == mono_defaults.object_class) {
4917 mono_class_setup_vtable (klass);
4918 for (i = 0; i < klass->vtable_size; ++i) {
4919 MonoMethod *cm = klass->vtable [i];
4921 if (!strcmp (cm->name, "GetHashCode"))
4923 else if (!strcmp (cm->name, "Finalize"))
4927 g_assert (ghc_slot > 0);
4928 default_ghc = klass->vtable [ghc_slot];
4930 g_assert (finalize_slot > 0);
4931 default_finalize = klass->vtable [finalize_slot];
4936 MonoMethod *array_method;
4938 } GenericArrayMethodInfo;
4940 static int generic_array_method_num = 0;
4941 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4944 generic_array_methods (MonoClass *klass)
4946 int i, count_generic = 0;
4947 GList *list = NULL, *tmp;
4948 if (generic_array_method_num)
4949 return generic_array_method_num;
4950 mono_class_setup_methods (klass->parent); /*This is setting up System.Array*/
4951 g_assert (!mono_class_has_failure (klass->parent)); /*So hitting this assert is a huge problem*/
4952 for (i = 0; i < klass->parent->method.count; i++) {
4953 MonoMethod *m = klass->parent->methods [i];
4954 if (!strncmp (m->name, "InternalArray__", 15)) {
4956 list = g_list_prepend (list, m);
4959 list = g_list_reverse (list);
4960 generic_array_method_info = (GenericArrayMethodInfo *)mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4962 for (tmp = list; tmp; tmp = tmp->next) {
4963 const char *mname, *iname;
4965 MonoMethod *m = (MonoMethod *)tmp->data;
4966 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4967 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4969 generic_array_method_info [i].array_method = m;
4970 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4971 iname = "System.Collections.Generic.ICollection`1.";
4972 mname = m->name + 27;
4973 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4974 iname = "System.Collections.Generic.IEnumerable`1.";
4975 mname = m->name + 27;
4976 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4977 iname = "System.Collections.Generic.IReadOnlyList`1.";
4978 mname = m->name + strlen (ireadonlylist_prefix);
4979 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4980 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4981 mname = m->name + strlen (ireadonlycollection_prefix);
4982 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4983 iname = "System.Collections.Generic.IList`1.";
4984 mname = m->name + 15;
4986 g_assert_not_reached ();
4989 name = (gchar *)mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4990 strcpy (name, iname);
4991 strcpy (name + strlen (iname), mname);
4992 generic_array_method_info [i].name = name;
4995 /*g_print ("array generic methods: %d\n", count_generic);*/
4997 generic_array_method_num = count_generic;
4999 return generic_array_method_num;
5003 setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos)
5005 MonoGenericContext tmp_context;
5008 tmp_context.class_inst = NULL;
5009 tmp_context.method_inst = iface->generic_class->context.class_inst;
5010 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
5012 for (i = 0; i < generic_array_method_num; i++) {
5014 MonoMethod *m = generic_array_method_info [i].array_method;
5015 MonoMethod *inflated;
5017 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
5018 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
5019 methods [pos++] = mono_marshal_get_generic_array_helper (klass, iface, generic_array_method_info [i].name, inflated);
5024 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
5026 int null_length = strlen ("(null)");
5027 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
5028 char *s = (char *)mono_image_alloc (image, len);
5031 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
5032 g_assert (result == len - 1);
5038 set_failure_from_loader_error (MonoClass *klass, MonoLoaderError *error)
5040 gpointer exception_data = NULL;
5042 switch (error->exception_type) {
5043 case MONO_EXCEPTION_TYPE_LOAD:
5044 exception_data = concat_two_strings_with_zero (klass->image, error->class_name, error->assembly_name);
5047 case MONO_EXCEPTION_MISSING_METHOD:
5048 exception_data = concat_two_strings_with_zero (klass->image, error->class_name, error->member_name);
5051 case MONO_EXCEPTION_MISSING_FIELD: {
5052 const char *name_space = error->klass->name_space ? error->klass->name_space : NULL;
5053 const char *class_name;
5056 class_name = g_strdup_printf ("%s.%s", name_space, error->klass->name);
5058 class_name = error->klass->name;
5060 exception_data = concat_two_strings_with_zero (klass->image, class_name, error->member_name);
5063 g_free ((void*)class_name);
5067 case MONO_EXCEPTION_FILE_NOT_FOUND: {
5070 if (error->ref_only)
5071 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.";
5073 msg = "Could not load file or assembly '%s' or one of its dependencies.";
5075 exception_data = concat_two_strings_with_zero (klass->image, msg, error->assembly_name);
5079 case MONO_EXCEPTION_BAD_IMAGE:
5080 exception_data = error->msg;
5084 g_assert_not_reached ();
5087 mono_class_set_failure (klass, error->exception_type, exception_data);
5092 * @class: the class to initialize
5094 * Compute the instance_size, class_size and other infos that cannot be
5095 * computed at mono_class_get() time. Also compute vtable_size if possible.
5096 * Returns TRUE on success or FALSE if there was a problem in loading
5097 * the type (incorrect assemblies, missing assemblies, methods, etc).
5099 * LOCKING: Acquires the loader lock.
5102 mono_class_init (MonoClass *klass)
5105 MonoCachedClassInfo cached_info;
5106 gboolean has_cached_info;
5110 /* Double-checking locking pattern */
5111 if (klass->inited || mono_class_has_failure (klass))
5112 return !mono_class_has_failure (klass);
5114 /*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/
5116 /* We do everything inside the lock to prevent races */
5117 mono_loader_lock ();
5119 if (klass->inited || mono_class_has_failure (klass)) {
5120 mono_loader_unlock ();
5121 /* Somebody might have gotten in before us */
5122 return !mono_class_has_failure (klass);
5125 if (klass->init_pending) {
5126 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Recursive type definition detected"));
5130 klass->init_pending = 1;
5132 if (mono_verifier_is_enabled_for_class (klass) && !mono_verifier_verify_class (klass)) {
5133 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, concat_two_strings_with_zero (klass->image, klass->name, klass->image->assembly_name));
5138 if (klass->byval_arg.type == MONO_TYPE_ARRAY || klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5139 MonoClass *element_class = klass->element_class;
5140 if (!element_class->inited)
5141 mono_class_init (element_class);
5142 if (mono_class_has_failure (element_class)) {
5143 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5148 mono_stats.initialized_class_count++;
5150 if (klass->generic_class && !klass->generic_class->is_dynamic) {
5151 MonoClass *gklass = klass->generic_class->container_class;
5153 mono_stats.generic_class_count++;
5155 klass->method = gklass->method;
5156 klass->field = gklass->field;
5158 mono_class_init (gklass);
5159 // FIXME: Why is this needed ?
5160 if (!mono_class_has_failure (gklass))
5161 mono_class_setup_methods (gklass);
5162 if (mono_class_has_failure (gklass)) {
5163 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic Type Defintion failed to init"));
5167 if (MONO_CLASS_IS_INTERFACE (klass))
5168 klass->interface_id = mono_get_unique_iid (klass);
5171 if (klass->parent && !klass->parent->inited)
5172 mono_class_init (klass->parent);
5174 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
5176 if (klass->generic_class || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
5177 klass->nested_classes_inited = TRUE;
5180 * Computes the size used by the fields, and their locations
5182 if (has_cached_info) {
5183 klass->instance_size = cached_info.instance_size;
5184 klass->sizes.class_size = cached_info.class_size;
5185 klass->packing_size = cached_info.packing_size;
5186 klass->min_align = cached_info.min_align;
5187 klass->blittable = cached_info.blittable;
5188 klass->has_references = cached_info.has_references;
5189 klass->has_static_refs = cached_info.has_static_refs;
5190 klass->no_special_static_fields = cached_info.no_special_static_fields;
5193 if (!klass->size_inited){
5194 mono_class_setup_fields (klass);
5195 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
5199 /* Initialize arrays */
5201 klass->method.count = 3 + (klass->rank > 1? 2: 1);
5203 if (klass->interface_count) {
5204 int count_generic = generic_array_methods (klass);
5205 klass->method.count += klass->interface_count * count_generic;
5209 mono_class_setup_supertypes (klass);
5212 initialize_object_slots (klass);
5215 * Initialize the rest of the data without creating a generic vtable if possible.
5216 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5217 * also avoid computing a generic vtable.
5219 if (has_cached_info) {
5221 klass->vtable_size = cached_info.vtable_size;
5222 klass->has_finalize = cached_info.has_finalize;
5223 klass->has_finalize_inited = TRUE;
5224 klass->ghcimpl = cached_info.ghcimpl;
5225 klass->has_cctor = cached_info.has_cctor;
5226 } else if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5227 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5228 * The first slot if for array with.
5230 static int szarray_vtable_size[2] = { 0 };
5232 int slot = MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg) ? 0 : 1;
5235 if (!szarray_vtable_size [slot]) {
5236 mono_class_setup_vtable (klass);
5237 szarray_vtable_size [slot] = klass->vtable_size;
5239 klass->vtable_size = szarray_vtable_size[slot];
5241 } else if (klass->generic_class && !MONO_CLASS_IS_INTERFACE (klass)) {
5242 MonoClass *gklass = klass->generic_class->container_class;
5244 /* Generic instance case */
5245 klass->ghcimpl = gklass->ghcimpl;
5246 klass->has_cctor = gklass->has_cctor;
5248 mono_class_setup_vtable (gklass);
5249 if (mono_class_has_failure (gklass)) {
5250 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5254 klass->vtable_size = gklass->vtable_size;
5258 /* ghcimpl is not currently used
5260 if (klass->parent) {
5261 MonoMethod *cmethod = klass->vtable [ghc_slot];
5262 if (cmethod->is_inflated)
5263 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5264 if (cmethod == default_ghc) {
5270 /* C# doesn't allow interfaces to have cctors */
5271 if (!MONO_CLASS_IS_INTERFACE (klass) || klass->image != mono_defaults.corlib) {
5272 MonoMethod *cmethod = NULL;
5274 if (klass->type_token && !image_is_dynamic(klass->image)) {
5275 cmethod = find_method_in_metadata (klass, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5276 /* The find_method function ignores the 'flags' argument */
5277 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5278 klass->has_cctor = 1;
5280 mono_class_setup_methods (klass);
5281 if (mono_class_has_failure (klass))
5284 for (i = 0; i < klass->method.count; ++i) {
5285 MonoMethod *method = klass->methods [i];
5286 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5287 (strcmp (".cctor", method->name) == 0)) {
5288 klass->has_cctor = 1;
5296 if (klass->parent) {
5297 int first_iface_slot;
5298 /* This will compute klass->parent->vtable_size for some classes */
5299 mono_class_init (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 ())
5306 if (!klass->parent->vtable_size) {
5307 /* FIXME: Get rid of this somehow */
5308 mono_class_setup_vtable (klass->parent);
5309 if (mono_class_has_failure (klass->parent)) {
5310 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5313 if (mono_loader_get_last_error ())
5316 first_iface_slot = klass->parent->vtable_size;
5317 if (mono_class_need_stelemref_method (klass))
5319 setup_interface_offsets (klass, first_iface_slot, TRUE);
5321 setup_interface_offsets (klass, 0, TRUE);
5324 if (mono_security_core_clr_enabled ())
5325 mono_security_core_clr_check_inheritance (klass);
5327 if (mono_loader_get_last_error ()) {
5328 if (!mono_class_has_failure (klass)) {
5329 set_failure_from_loader_error (klass, mono_loader_get_last_error ());
5331 mono_loader_clear_error ();
5334 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass))
5335 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Invalid generic instantiation"));
5340 /* Because of the double-checking locking pattern */
5341 mono_memory_barrier ();
5343 klass->init_pending = 0;
5345 mono_loader_unlock ();
5347 return !mono_class_has_failure (klass);
5351 * mono_class_has_finalizer:
5353 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5357 mono_class_has_finalizer (MonoClass *klass)
5359 gboolean has_finalize = FALSE;
5361 if (klass->has_finalize_inited)
5362 return klass->has_finalize;
5364 /* Interfaces and valuetypes are not supposed to have finalizers */
5365 if (!(MONO_CLASS_IS_INTERFACE (klass) || klass->valuetype)) {
5366 MonoMethod *cmethod = NULL;
5368 if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5369 } else if (klass->generic_class) {
5370 MonoClass *gklass = klass->generic_class->container_class;
5372 has_finalize = mono_class_has_finalizer (gklass);
5373 } else if (klass->parent && klass->parent->has_finalize) {
5374 has_finalize = TRUE;
5376 if (klass->parent) {
5378 * Can't search in metadata for a method named Finalize, because that
5379 * ignores overrides.
5381 mono_class_setup_vtable (klass);
5382 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
5385 cmethod = klass->vtable [finalize_slot];
5389 g_assert (klass->vtable_size > finalize_slot);
5391 if (klass->parent) {
5392 if (cmethod->is_inflated)
5393 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5394 if (cmethod != default_finalize)
5395 has_finalize = TRUE;
5401 mono_image_lock (klass->image);
5403 if (!klass->has_finalize_inited) {
5404 klass->has_finalize = has_finalize ? 1 : 0;
5406 mono_memory_barrier ();
5407 klass->has_finalize_inited = TRUE;
5410 mono_image_unlock (klass->image);
5412 return klass->has_finalize;
5416 mono_is_corlib_image (MonoImage *image)
5418 /* FIXME: allow the dynamic case for our compilers and with full trust */
5419 if (image_is_dynamic (image))
5420 return image->assembly && !strcmp (image->assembly->aname.name, "mscorlib");
5422 return image == mono_defaults.corlib;
5426 * LOCKING: this assumes the loader lock is held
5429 mono_class_setup_mono_type (MonoClass *klass)
5431 const char *name = klass->name;
5432 const char *nspace = klass->name_space;
5433 gboolean is_corlib = mono_is_corlib_image (klass->image);
5435 klass->this_arg.byref = 1;
5436 klass->this_arg.data.klass = klass;
5437 klass->this_arg.type = MONO_TYPE_CLASS;
5438 klass->byval_arg.data.klass = klass;
5439 klass->byval_arg.type = MONO_TYPE_CLASS;
5441 if (is_corlib && !strcmp (nspace, "System")) {
5442 if (!strcmp (name, "ValueType")) {
5444 * do not set the valuetype bit for System.ValueType.
5445 * klass->valuetype = 1;
5447 klass->blittable = TRUE;
5448 } else if (!strcmp (name, "Enum")) {
5450 * do not set the valuetype bit for System.Enum.
5451 * klass->valuetype = 1;
5453 klass->valuetype = 0;
5454 klass->enumtype = 0;
5455 } else if (!strcmp (name, "Object")) {
5456 klass->byval_arg.type = MONO_TYPE_OBJECT;
5457 klass->this_arg.type = MONO_TYPE_OBJECT;
5458 } else if (!strcmp (name, "String")) {
5459 klass->byval_arg.type = MONO_TYPE_STRING;
5460 klass->this_arg.type = MONO_TYPE_STRING;
5461 } else if (!strcmp (name, "TypedReference")) {
5462 klass->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5463 klass->this_arg.type = MONO_TYPE_TYPEDBYREF;
5467 if (klass->valuetype) {
5468 int t = MONO_TYPE_VALUETYPE;
5470 if (is_corlib && !strcmp (nspace, "System")) {
5473 if (!strcmp (name, "Boolean")) {
5474 t = MONO_TYPE_BOOLEAN;
5475 } else if (!strcmp(name, "Byte")) {
5477 klass->blittable = TRUE;
5481 if (!strcmp (name, "Char")) {
5486 if (!strcmp (name, "Double")) {
5488 klass->blittable = TRUE;
5492 if (!strcmp (name, "Int32")) {
5494 klass->blittable = TRUE;
5495 } else if (!strcmp(name, "Int16")) {
5497 klass->blittable = TRUE;
5498 } else if (!strcmp(name, "Int64")) {
5500 klass->blittable = TRUE;
5501 } else if (!strcmp(name, "IntPtr")) {
5503 klass->blittable = TRUE;
5507 if (!strcmp (name, "Single")) {
5509 klass->blittable = TRUE;
5510 } else if (!strcmp(name, "SByte")) {
5512 klass->blittable = TRUE;
5516 if (!strcmp (name, "UInt32")) {
5518 klass->blittable = TRUE;
5519 } else if (!strcmp(name, "UInt16")) {
5521 klass->blittable = TRUE;
5522 } else if (!strcmp(name, "UInt64")) {
5524 klass->blittable = TRUE;
5525 } else if (!strcmp(name, "UIntPtr")) {
5527 klass->blittable = TRUE;
5531 if (!strcmp (name, "TypedReference")) {
5532 t = MONO_TYPE_TYPEDBYREF;
5533 klass->blittable = TRUE;
5537 if (!strcmp (name, "Void")) {
5545 klass->byval_arg.type = (MonoTypeEnum)t;
5546 klass->this_arg.type = (MonoTypeEnum)t;
5549 if (MONO_CLASS_IS_INTERFACE (klass))
5550 klass->interface_id = mono_get_unique_iid (klass);
5556 * COM initialization is delayed until needed.
5557 * However when a [ComImport] attribute is present on a type it will trigger
5558 * the initialization. This is not a problem unless the BCL being executed
5559 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5562 init_com_from_comimport (MonoClass *klass)
5564 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5565 if (mono_security_core_clr_enabled ()) {
5566 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5567 if (!mono_security_core_clr_determine_platform_image (klass->image)) {
5568 /* but it can not be made available for application (i.e. user code) since all COM calls
5569 * are considered native calls. In this case we fail with a TypeLoadException (just like
5570 * Silverlight 2 does */
5571 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5576 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5578 #endif /*DISABLE_COM*/
5581 * LOCKING: this assumes the loader lock is held
5584 mono_class_setup_parent (MonoClass *klass, MonoClass *parent)
5586 gboolean system_namespace;
5587 gboolean is_corlib = mono_is_corlib_image (klass->image);
5589 system_namespace = !strcmp (klass->name_space, "System") && is_corlib;
5591 /* if root of the hierarchy */
5592 if (system_namespace && !strcmp (klass->name, "Object")) {
5593 klass->parent = NULL;
5594 klass->instance_size = sizeof (MonoObject);
5597 if (!strcmp (klass->name, "<Module>")) {
5598 klass->parent = NULL;
5599 klass->instance_size = 0;
5603 if (!MONO_CLASS_IS_INTERFACE (klass)) {
5604 /* Imported COM Objects always derive from __ComObject. */
5606 if (MONO_CLASS_IS_IMPORT (klass)) {
5607 init_com_from_comimport (klass);
5608 if (parent == mono_defaults.object_class)
5609 parent = mono_class_get_com_object_class ();
5613 /* set the parent to something useful and safe, but mark the type as broken */
5614 parent = mono_defaults.object_class;
5615 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5618 klass->parent = parent;
5620 if (parent->generic_class && !parent->name) {
5622 * If the parent is a generic instance, we may get
5623 * called before it is fully initialized, especially
5624 * before it has its name.
5629 #ifndef DISABLE_REMOTING
5630 klass->marshalbyref = parent->marshalbyref;
5631 klass->contextbound = parent->contextbound;
5634 klass->delegate = parent->delegate;
5636 if (MONO_CLASS_IS_IMPORT (klass) || mono_class_is_com_object (parent))
5637 mono_class_set_is_com_object (klass);
5639 if (system_namespace) {
5640 #ifndef DISABLE_REMOTING
5641 if (klass->name [0] == 'M' && !strcmp (klass->name, "MarshalByRefObject"))
5642 klass->marshalbyref = 1;
5644 if (klass->name [0] == 'C' && !strcmp (klass->name, "ContextBoundObject"))
5645 klass->contextbound = 1;
5647 if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate"))
5648 klass->delegate = 1;
5651 if (klass->parent->enumtype || (mono_is_corlib_image (klass->parent->image) && (strcmp (klass->parent->name, "ValueType") == 0) &&
5652 (strcmp (klass->parent->name_space, "System") == 0)))
5653 klass->valuetype = 1;
5654 if (mono_is_corlib_image (klass->parent->image) && ((strcmp (klass->parent->name, "Enum") == 0) && (strcmp (klass->parent->name_space, "System") == 0))) {
5655 klass->valuetype = klass->enumtype = 1;
5657 /*klass->enumtype = klass->parent->enumtype; */
5659 /* initialize com types if COM interfaces are present */
5661 if (MONO_CLASS_IS_IMPORT (klass))
5662 init_com_from_comimport (klass);
5664 klass->parent = NULL;
5670 * mono_class_setup_supertypes:
5673 * Build the data structure needed to make fast type checks work.
5674 * This currently sets two fields in @class:
5675 * - idepth: distance between @class and System.Object in the type
5677 * - supertypes: array of classes: each element has a class in the hierarchy
5678 * starting from @class up to System.Object
5680 * LOCKING: This function is atomic, in case of contention we waste memory.
5683 mono_class_setup_supertypes (MonoClass *klass)
5686 MonoClass **supertypes;
5688 mono_atomic_load_acquire (supertypes, MonoClass **, &klass->supertypes);
5692 if (klass->parent && !klass->parent->supertypes)
5693 mono_class_setup_supertypes (klass->parent);
5695 klass->idepth = klass->parent->idepth + 1;
5699 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, klass->idepth);
5700 supertypes = (MonoClass **)mono_class_alloc0 (klass, sizeof (MonoClass *) * ms);
5702 if (klass->parent) {
5703 CHECKED_METADATA_WRITE_PTR ( supertypes [klass->idepth - 1] , klass );
5706 for (supertype_idx = 0; supertype_idx < klass->parent->idepth; supertype_idx++)
5707 CHECKED_METADATA_WRITE_PTR ( supertypes [supertype_idx] , klass->parent->supertypes [supertype_idx] );
5709 CHECKED_METADATA_WRITE_PTR ( supertypes [0] , klass );
5712 CHECKED_METADATA_WRITE_PTR_ATOMIC ( klass->supertypes , supertypes );
5716 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5718 MonoClass *gtd = (MonoClass*)user_data;
5719 /* Only try to fix generic instances of @gtd */
5720 if (gclass->generic_class->container_class != gtd)
5723 /* Check if the generic instance has no parent. */
5724 if (gtd->parent && !gclass->parent)
5725 mono_generic_class_setup_parent (gclass, gtd);
5731 mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char *msg)
5733 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (msg));
5734 mono_error_set_type_load_class (error, klass, msg);
5738 mono_class_set_failure_from_loader_error (MonoClass *klass, MonoError *error, char *msg)
5740 MonoLoaderError *lerror = mono_loader_get_last_error ();
5743 set_failure_from_loader_error (klass, lerror);
5744 mono_error_set_from_loader_error (error);
5748 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, msg);
5749 mono_error_set_type_load_class (error, klass, msg);
5754 * mono_class_create_from_typedef:
5755 * @image: image where the token is valid
5756 * @type_token: typedef token
5757 * @error: used to return any error found while creating the type
5759 * Create the MonoClass* representing the specified type token.
5760 * @type_token must be a TypeDef token.
5762 * FIXME: don't return NULL on failure, just the the caller figure it out.
5765 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5767 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5768 MonoClass *klass, *parent = NULL;
5769 guint32 cols [MONO_TYPEDEF_SIZE];
5770 guint32 cols_next [MONO_TYPEDEF_SIZE];
5771 guint tidx = mono_metadata_token_index (type_token);
5772 MonoGenericContext *context = NULL;
5773 const char *name, *nspace;
5775 MonoClass **interfaces;
5776 guint32 field_last, method_last;
5777 guint32 nesting_tokeen;
5779 mono_error_init (error);
5781 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5782 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5783 mono_loader_assert_no_error ();
5787 mono_loader_lock ();
5789 if ((klass = (MonoClass *)mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5790 mono_loader_unlock ();
5791 mono_loader_assert_no_error ();
5795 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5797 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5798 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5800 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
5803 klass->name_space = nspace;
5805 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5807 klass->image = image;
5808 klass->type_token = type_token;
5809 klass->flags = cols [MONO_TYPEDEF_FLAGS];
5811 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
5813 classes_size += sizeof (MonoClass);
5816 * Check whether we're a generic type definition.
5818 klass->generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
5819 if (klass->generic_container) {
5820 klass->is_generic = 1;
5821 klass->generic_container->owner.klass = klass;
5822 klass->generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
5823 context = &klass->generic_container->context;
5826 if (klass->generic_container)
5827 enable_gclass_recording ();
5829 if (cols [MONO_TYPEDEF_EXTENDS]) {
5831 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5833 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5834 /*WARNING: this must satisfy mono_metadata_type_hash*/
5835 klass->this_arg.byref = 1;
5836 klass->this_arg.data.klass = klass;
5837 klass->this_arg.type = MONO_TYPE_CLASS;
5838 klass->byval_arg.data.klass = klass;
5839 klass->byval_arg.type = MONO_TYPE_CLASS;
5841 parent = mono_class_get_checked (image, parent_token, error);
5842 if (parent && context) /* Always inflate */
5843 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5845 if (parent == NULL) {
5846 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5847 goto parent_failure;
5850 for (tmp = parent; tmp; tmp = tmp->parent) {
5852 mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
5853 goto parent_failure;
5855 if (klass->generic_container && tmp->generic_class && tmp->generic_class->container_class == klass) {
5856 mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
5857 goto parent_failure;
5862 mono_class_setup_parent (klass, parent);
5864 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5865 mono_class_setup_mono_type (klass);
5867 if (klass->generic_container)
5868 disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
5871 * This might access klass->byval_arg for recursion generated by generic constraints,
5872 * so it has to come after setup_mono_type ().
5874 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5875 klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5876 if (!mono_error_ok (error)) {
5877 /*FIXME implement a mono_class_set_failure_from_mono_error */
5878 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5879 mono_loader_unlock ();
5880 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5881 mono_loader_assert_no_error ();
5886 if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5890 if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5894 klass->cast_class = klass->element_class = klass;
5896 if (!klass->enumtype) {
5897 if (!mono_metadata_interfaces_from_typedef_full (
5898 image, type_token, &interfaces, &icount, FALSE, context, error)){
5900 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5901 mono_loader_unlock ();
5902 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5906 klass->interfaces = interfaces;
5907 klass->interface_count = icount;
5908 klass->interfaces_inited = 1;
5911 /*g_print ("Load class %s\n", name);*/
5914 * Compute the field and method lists
5916 klass->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5917 klass->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5919 if (tt->rows > tidx){
5920 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5921 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5922 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5924 field_last = image->tables [MONO_TABLE_FIELD].rows;
5925 method_last = image->tables [MONO_TABLE_METHOD].rows;
5928 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5929 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5930 klass->field.count = field_last - klass->field.first;
5932 klass->field.count = 0;
5934 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5935 klass->method.count = method_last - klass->method.first;
5937 klass->method.count = 0;
5939 /* reserve space to store vector pointer in arrays */
5940 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5941 klass->instance_size += 2 * sizeof (gpointer);
5942 g_assert (klass->field.count == 0);
5945 if (klass->enumtype) {
5946 MonoType *enum_basetype = mono_class_find_enum_basetype (klass, error);
5947 if (!enum_basetype) {
5948 /*set it to a default value as the whole runtime can't handle this to be null*/
5949 klass->cast_class = klass->element_class = mono_defaults.int32_class;
5950 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5951 mono_loader_unlock ();
5952 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5953 mono_loader_assert_no_error ();
5956 klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
5960 * If we're a generic type definition, load the constraints.
5961 * We must do this after the class has been constructed to make certain recursive scenarios
5964 if (klass->generic_container && !mono_metadata_load_generic_param_constraints_checked (image, type_token, klass->generic_container, error)) {
5965 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)));
5966 mono_loader_unlock ();
5967 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5968 mono_loader_assert_no_error ();
5972 if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5973 if (!strncmp (name, "Vector", 6))
5974 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");
5977 mono_loader_unlock ();
5979 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5980 mono_loader_assert_no_error ();
5985 mono_class_setup_mono_type (klass);
5986 mono_loader_unlock ();
5987 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5988 mono_loader_assert_no_error ();
5992 /** Is klass a Nullable<T> ginst? */
5994 mono_class_is_nullable (MonoClass *klass)
5996 return klass->generic_class != NULL &&
5997 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
6001 /** if klass is T? return T */
6003 mono_class_get_nullable_param (MonoClass *klass)
6005 g_assert (mono_class_is_nullable (klass));
6006 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
6010 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
6014 MonoGenericClass *gclass = klass->generic_class;
6016 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
6017 if (!mono_error_ok (&error)) {
6018 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
6019 klass->parent = mono_defaults.object_class;
6020 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
6021 mono_error_cleanup (&error);
6025 mono_class_setup_parent (klass, klass->parent);
6027 if (klass->enumtype) {
6028 klass->cast_class = gtd->cast_class;
6029 klass->element_class = gtd->element_class;
6035 * Create the `MonoClass' for an instantiation of a generic type.
6036 * We only do this if we actually need it.
6039 mono_generic_class_get_class (MonoGenericClass *gclass)
6041 MonoClass *klass, *gklass;
6043 if (gclass->cached_class)
6044 return gclass->cached_class;
6046 mono_loader_lock ();
6047 if (gclass->cached_class) {
6048 mono_loader_unlock ();
6049 return gclass->cached_class;
6052 klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
6054 gklass = gclass->container_class;
6056 if (record_gclass_instantiation > 0)
6057 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
6059 if (gklass->nested_in) {
6060 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
6061 klass->nested_in = gklass->nested_in;
6064 klass->name = gklass->name;
6065 klass->name_space = gklass->name_space;
6067 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6069 klass->image = gklass->image;
6070 klass->flags = gklass->flags;
6071 klass->type_token = gklass->type_token;
6072 klass->field.count = gklass->field.count;
6074 klass->is_inflated = 1;
6075 klass->generic_class = gclass;
6077 klass->byval_arg.type = MONO_TYPE_GENERICINST;
6078 klass->this_arg.type = klass->byval_arg.type;
6079 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
6080 klass->this_arg.byref = TRUE;
6081 klass->enumtype = gklass->enumtype;
6082 klass->valuetype = gklass->valuetype;
6084 klass->cast_class = klass->element_class = klass;
6086 if (mono_class_is_nullable (klass))
6087 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
6090 * We're not interested in the nested classes of a generic instance.
6091 * We use the generic type definition to look for nested classes.
6094 mono_generic_class_setup_parent (klass, gklass);
6096 if (gclass->is_dynamic) {
6098 * 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.
6099 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
6100 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
6102 if (!gklass->wastypebuilder)
6105 mono_class_setup_supertypes (klass);
6107 if (klass->enumtype) {
6109 * For enums, gklass->fields might not been set, but instance_size etc. is
6110 * already set in mono_reflection_create_internal_class (). For non-enums,
6111 * these will be computed normally in mono_class_layout_fields ().
6113 klass->instance_size = gklass->instance_size;
6114 klass->sizes.class_size = gklass->sizes.class_size;
6115 mono_memory_barrier ();
6116 klass->size_inited = 1;
6120 mono_memory_barrier ();
6121 gclass->cached_class = klass;
6123 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6125 inflated_classes ++;
6126 inflated_classes_size += sizeof (MonoClass);
6128 mono_loader_unlock ();
6134 get_image_for_container (MonoGenericContainer *container)
6137 if (container->is_anonymous) {
6138 result = container->owner.image;
6141 if (container->is_method) {
6142 MonoMethod *method = container->owner.method;
6143 g_assert_checked (method);
6144 klass = method->klass;
6146 klass = container->owner.klass;
6148 g_assert_checked (klass);
6149 result = klass->image;
6156 get_image_for_generic_param (MonoGenericParam *param)
6158 MonoGenericContainer *container = mono_generic_param_owner (param);
6159 g_assert_checked (container);
6160 return get_image_for_container (container);
6163 // Make a string in the designated image consisting of a single integer.
6164 #define INT_STRING_SIZE 16
6166 make_generic_name_string (MonoImage *image, int num)
6168 char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
6169 g_snprintf (name, INT_STRING_SIZE, "%d", num);
6173 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
6174 // pinfo is derived from param by the caller for us.
6176 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
6178 MonoClass *klass, **ptr;
6180 MonoGenericContainer *container = mono_generic_param_owner (param);
6181 g_assert_checked (container);
6183 MonoImage *image = get_image_for_container (container);
6184 gboolean is_mvar = container->is_method;
6185 gboolean is_anonymous = container->is_anonymous;
6187 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6188 classes_size += sizeof (MonoClass);
6191 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
6193 int n = mono_generic_param_num (param);
6194 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
6198 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , "" );
6199 } else if (is_mvar) {
6200 MonoMethod *omethod = container->owner.method;
6201 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
6203 MonoClass *oklass = container->owner.klass;
6204 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
6207 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6209 // Count non-NULL items in pinfo->constraints
6212 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6216 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6217 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
6219 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
6220 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
6222 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
6225 if (count - pos > 0) {
6226 klass->interface_count = count - pos;
6227 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
6228 klass->interfaces_inited = TRUE;
6229 for (i = pos; i < count; i++)
6230 CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
6233 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
6235 klass->inited = TRUE;
6236 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class , klass );
6237 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
6238 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
6240 klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6241 klass->this_arg.type = klass->byval_arg.type;
6242 CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param , param );
6243 CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
6244 klass->this_arg.byref = TRUE;
6246 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6247 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6249 /*Init these fields to sane values*/
6250 klass->min_align = 1;
6252 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6253 * constrained to, the JIT depends on this.
6255 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6256 mono_memory_barrier ();
6257 klass->size_inited = 1;
6258 klass->setup_fields_called = 1;
6260 mono_class_setup_supertypes (klass);
6262 if (count - pos > 0) {
6263 mono_class_setup_vtable (klass->parent);
6264 if (mono_class_has_failure (klass->parent))
6265 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
6267 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6273 #define FAST_CACHE_SIZE 16
6276 * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6277 * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6278 * we cache the MonoClasses.
6279 * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6280 * LOCKING: Takes the image lock depending on @take_lock.
6283 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6285 int n = mono_generic_param_num (param);
6286 MonoImage *image = get_image_for_generic_param (param);
6287 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6288 MonoClass *klass = NULL;
6293 // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6294 // For high numbers or constraints we have to use pointer hashes.
6295 if (param->gshared_constraint) {
6296 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6299 mono_image_lock (image);
6300 klass = (MonoClass *)g_hash_table_lookup (ht, param);
6302 mono_image_unlock (image);
6307 if (n < FAST_CACHE_SIZE) {
6309 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6311 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6313 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6316 mono_image_lock (image);
6317 klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6319 mono_image_unlock (image);
6326 * LOCKING: Image lock (param->image) must be held
6329 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6331 int n = mono_generic_param_num (param);
6332 MonoImage *image = get_image_for_generic_param (param);
6333 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6337 if (param->gshared_constraint) {
6338 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6340 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6341 mono_memory_barrier ();
6343 image->mvar_cache_constrained = ht;
6345 image->var_cache_constrained = ht;
6347 g_hash_table_insert (ht, param, klass);
6348 } else if (n < FAST_CACHE_SIZE) {
6350 /* Requires locking to avoid droping an already published class */
6351 if (!image->mvar_cache_fast)
6352 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6353 image->mvar_cache_fast [n] = klass;
6355 if (!image->var_cache_fast)
6356 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6357 image->var_cache_fast [n] = klass;
6360 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6362 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6364 ht = g_hash_table_new (NULL, NULL);
6365 mono_memory_barrier ();
6367 image->mvar_cache_slow = ht;
6369 image->var_cache_slow = ht;
6372 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6377 * LOCKING: Acquires the image lock (@image).
6380 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6382 MonoImage *image = get_image_for_generic_param (param);
6383 MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6384 MonoClass *klass, *klass2;
6386 // If a klass already exists for this object and is cached, return it.
6387 if (pinfo) // Non-anonymous
6388 klass = pinfo->pklass;
6390 klass = get_anon_gparam_class (param, TRUE);
6395 // Create a new klass
6396 klass = make_generic_param_class (param, pinfo);
6398 // Now we need to cache the klass we created.
6399 // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6400 // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6401 // and allow our newly-created klass object to just leak.
6402 mono_memory_barrier ();
6404 mono_image_lock (image);
6406 // Here "klass2" refers to the klass potentially created by the other thread.
6407 if (pinfo) // Repeat check from above
6408 klass2 = pinfo->pklass;
6410 klass2 = get_anon_gparam_class (param, FALSE);
6417 pinfo->pklass = klass;
6419 set_anon_gparam_class (param, klass);
6421 mono_image_unlock (image);
6423 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6425 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED); // Alert profiler about botched class create
6427 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6433 * mono_class_from_generic_parameter:
6434 * @param: Parameter to find/construct a class for.
6435 * @arg2: Is ignored.
6436 * @arg3: Is ignored.
6439 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6441 return mono_class_from_generic_parameter_internal (param);
6446 mono_ptr_class_get (MonoType *type)
6449 MonoClass *el_class;
6453 el_class = mono_class_from_mono_type (type);
6454 image = el_class->image;
6456 mono_image_lock (image);
6457 if (image->ptr_cache) {
6458 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6459 mono_image_unlock (image);
6463 mono_image_unlock (image);
6465 result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6467 classes_size += sizeof (MonoClass);
6469 result->parent = NULL; /* no parent for PTR types */
6470 result->name_space = el_class->name_space;
6471 name = g_strdup_printf ("%s*", el_class->name);
6472 result->name = mono_image_strdup (image, name);
6475 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6477 result->image = el_class->image;
6478 result->inited = TRUE;
6479 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6480 /* Can pointers get boxed? */
6481 result->instance_size = sizeof (gpointer);
6482 result->cast_class = result->element_class = el_class;
6483 result->blittable = TRUE;
6485 result->byval_arg.type = MONO_TYPE_PTR;
6486 result->this_arg.type = result->byval_arg.type;
6487 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6488 result->this_arg.byref = TRUE;
6490 mono_class_setup_supertypes (result);
6492 mono_image_lock (image);
6493 if (image->ptr_cache) {
6495 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6496 mono_image_unlock (image);
6497 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6501 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6503 g_hash_table_insert (image->ptr_cache, el_class, result);
6504 mono_image_unlock (image);
6506 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6512 mono_fnptr_class_get (MonoMethodSignature *sig)
6515 static GHashTable *ptr_hash = NULL;
6517 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6519 mono_loader_lock ();
6522 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6524 if ((result = (MonoClass *)g_hash_table_lookup (ptr_hash, sig))) {
6525 mono_loader_unlock ();
6528 result = g_new0 (MonoClass, 1);
6530 result->parent = NULL; /* no parent for PTR types */
6531 result->name_space = "System";
6532 result->name = "MonoFNPtrFakeClass";
6534 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6536 result->image = mono_defaults.corlib; /* need to fix... */
6537 result->inited = TRUE;
6538 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6539 /* Can pointers get boxed? */
6540 result->instance_size = sizeof (gpointer);
6541 result->cast_class = result->element_class = result;
6542 result->blittable = TRUE;
6544 result->byval_arg.type = MONO_TYPE_FNPTR;
6545 result->this_arg.type = result->byval_arg.type;
6546 result->this_arg.data.method = result->byval_arg.data.method = sig;
6547 result->this_arg.byref = TRUE;
6548 result->blittable = TRUE;
6550 mono_class_setup_supertypes (result);
6552 g_hash_table_insert (ptr_hash, sig, result);
6554 mono_loader_unlock ();
6556 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6562 * mono_class_from_mono_type:
6563 * @type: describes the type to return
6565 * This returns a MonoClass for the specified MonoType, the value is never NULL.
6568 mono_class_from_mono_type (MonoType *type)
6570 switch (type->type) {
6571 case MONO_TYPE_OBJECT:
6572 return type->data.klass? type->data.klass: mono_defaults.object_class;
6573 case MONO_TYPE_VOID:
6574 return type->data.klass? type->data.klass: mono_defaults.void_class;
6575 case MONO_TYPE_BOOLEAN:
6576 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6577 case MONO_TYPE_CHAR:
6578 return type->data.klass? type->data.klass: mono_defaults.char_class;
6580 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6582 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6584 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6586 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6588 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6590 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6592 return type->data.klass? type->data.klass: mono_defaults.int_class;
6594 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6596 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6598 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6600 return type->data.klass? type->data.klass: mono_defaults.single_class;
6602 return type->data.klass? type->data.klass: mono_defaults.double_class;
6603 case MONO_TYPE_STRING:
6604 return type->data.klass? type->data.klass: mono_defaults.string_class;
6605 case MONO_TYPE_TYPEDBYREF:
6606 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6607 case MONO_TYPE_ARRAY:
6608 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6610 return mono_ptr_class_get (type->data.type);
6611 case MONO_TYPE_FNPTR:
6612 return mono_fnptr_class_get (type->data.method);
6613 case MONO_TYPE_SZARRAY:
6614 return mono_array_class_get (type->data.klass, 1);
6615 case MONO_TYPE_CLASS:
6616 case MONO_TYPE_VALUETYPE:
6617 return type->data.klass;
6618 case MONO_TYPE_GENERICINST:
6619 return mono_generic_class_get_class (type->data.generic_class);
6620 case MONO_TYPE_MVAR:
6622 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6624 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6625 g_assert_not_reached ();
6628 // Yes, this returns NULL, even if it is documented as not doing so, but there
6629 // is no way for the code to make it this far, due to the assert above.
6634 * mono_type_retrieve_from_typespec
6635 * @image: context where the image is created
6636 * @type_spec: typespec token
6637 * @context: the generic context used to evaluate generic instantiations in
6640 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6642 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6644 *did_inflate = FALSE;
6649 if (context && (context->class_inst || context->method_inst)) {
6650 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6652 if (!mono_error_ok (error)) {
6653 mono_loader_assert_no_error ();
6659 *did_inflate = TRUE;
6666 * mono_class_create_from_typespec
6667 * @image: context where the image is created
6668 * @type_spec: typespec token
6669 * @context: the generic context used to evaluate generic instantiations in
6672 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6675 gboolean inflated = FALSE;
6676 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6677 return_val_if_nok (error, NULL);
6678 ret = mono_class_from_mono_type (t);
6680 mono_metadata_free_type (t);
6685 * mono_bounded_array_class_get:
6686 * @element_class: element class
6687 * @rank: the dimension of the array class
6688 * @bounded: whenever the array has non-zero bounds
6690 * Returns: A class object describing the array with element type @element_type and
6694 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6698 MonoClass *parent = NULL;
6699 GSList *list, *rootlist = NULL;
6702 gboolean corlib_type = FALSE;
6704 g_assert (rank <= 255);
6707 /* bounded only matters for one-dimensional arrays */
6710 image = eclass->image;
6712 if (rank == 1 && !bounded) {
6714 * This case is very frequent not just during compilation because of calls
6715 * from mono_class_from_mono_type (), mono_array_new (),
6716 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6718 mono_os_mutex_lock (&image->szarray_cache_lock);
6719 if (!image->szarray_cache)
6720 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6721 klass = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6722 mono_os_mutex_unlock (&image->szarray_cache_lock);
6726 mono_loader_lock ();
6728 mono_loader_lock ();
6730 if (!image->array_cache)
6731 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6733 if ((rootlist = list = (GSList *)g_hash_table_lookup (image->array_cache, eclass))) {
6734 for (; list; list = list->next) {
6735 klass = (MonoClass *)list->data;
6736 if ((klass->rank == rank) && (klass->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6737 mono_loader_unlock ();
6744 /* for the building corlib use System.Array from it */
6745 if (image->assembly && assembly_is_dynamic (image->assembly) && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6746 parent = mono_class_load_from_name (image, "System", "Array");
6749 parent = mono_defaults.array_class;
6750 if (!parent->inited)
6751 mono_class_init (parent);
6754 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6756 klass->image = image;
6757 klass->name_space = eclass->name_space;
6758 nsize = strlen (eclass->name);
6759 name = (char *)g_malloc (nsize + 2 + rank + 1);
6760 memcpy (name, eclass->name, nsize);
6763 memset (name + nsize + 1, ',', rank - 1);
6765 name [nsize + rank] = '*';
6766 name [nsize + rank + bounded] = ']';
6767 name [nsize + rank + bounded + 1] = 0;
6768 klass->name = mono_image_strdup (image, name);
6771 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6773 classes_size += sizeof (MonoClass);
6775 klass->type_token = 0;
6776 /* all arrays are marked serializable and sealed, bug #42779 */
6777 klass->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6778 klass->parent = parent;
6779 klass->instance_size = mono_class_instance_size (klass->parent);
6781 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6782 /*Arrays of those two types are invalid.*/
6783 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
6784 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6785 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6786 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6787 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6789 /* element_size -1 is ok as this is not an instantitable type*/
6790 klass->sizes.element_size = -1;
6792 klass->sizes.element_size = mono_class_array_element_size (eclass);
6794 mono_class_setup_supertypes (klass);
6796 if (eclass->generic_class)
6797 mono_class_init (eclass);
6798 if (!eclass->size_inited)
6799 mono_class_setup_fields (eclass);
6800 if (mono_class_has_failure (eclass)) /*FIXME we fail the array type, but we have to let other fields be set.*/
6801 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
6803 klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6807 if (eclass->enumtype)
6808 klass->cast_class = eclass->element_class;
6810 klass->cast_class = eclass;
6812 switch (klass->cast_class->byval_arg.type) {
6814 klass->cast_class = mono_defaults.byte_class;
6817 klass->cast_class = mono_defaults.int16_class;
6820 #if SIZEOF_VOID_P == 4
6824 klass->cast_class = mono_defaults.int32_class;
6827 #if SIZEOF_VOID_P == 8
6831 klass->cast_class = mono_defaults.int64_class;
6837 klass->element_class = eclass;
6839 if ((rank > 1) || bounded) {
6840 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6841 klass->byval_arg.type = MONO_TYPE_ARRAY;
6842 klass->byval_arg.data.array = at;
6843 at->eklass = eclass;
6845 /* FIXME: complete.... */
6847 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6848 klass->byval_arg.data.klass = eclass;
6850 klass->this_arg = klass->byval_arg;
6851 klass->this_arg.byref = 1;
6856 klass->generic_container = eclass->generic_container;
6858 if (rank == 1 && !bounded) {
6859 MonoClass *prev_class;
6861 mono_os_mutex_lock (&image->szarray_cache_lock);
6862 prev_class = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6864 /* Someone got in before us */
6867 g_hash_table_insert (image->szarray_cache, eclass, klass);
6868 mono_os_mutex_unlock (&image->szarray_cache_lock);
6870 list = g_slist_append (rootlist, klass);
6871 g_hash_table_insert (image->array_cache, eclass, list);
6874 mono_loader_unlock ();
6876 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6882 * mono_array_class_get:
6883 * @element_class: element class
6884 * @rank: the dimension of the array class
6886 * Returns: A class object describing the array with element type @element_type and
6890 mono_array_class_get (MonoClass *eclass, guint32 rank)
6892 return mono_bounded_array_class_get (eclass, rank, FALSE);
6896 * mono_class_instance_size:
6899 * Use to get the size of a class in bytes.
6901 * Returns: The size of an object instance
6904 mono_class_instance_size (MonoClass *klass)
6906 if (!klass->size_inited)
6907 mono_class_init (klass);
6909 return klass->instance_size;
6913 * mono_class_min_align:
6916 * Use to get the computed minimum alignment requirements for the specified class.
6918 * Returns: minimm alignment requirements
6921 mono_class_min_align (MonoClass *klass)
6923 if (!klass->size_inited)
6924 mono_class_init (klass);
6926 return klass->min_align;
6930 * mono_class_value_size:
6933 * This function is used for value types, and return the
6934 * space and the alignment to store that kind of value object.
6936 * Returns: the size of a value of kind @klass
6939 mono_class_value_size (MonoClass *klass, guint32 *align)
6943 /* fixme: check disable, because we still have external revereces to
6944 * mscorlib and Dummy Objects
6946 /*g_assert (klass->valuetype);*/
6948 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6951 *align = klass->min_align;
6957 * mono_class_data_size:
6960 * Returns: The size of the static class data
6963 mono_class_data_size (MonoClass *klass)
6966 mono_class_init (klass);
6967 /* This can happen with dynamically created types */
6968 if (!klass->fields_inited)
6969 mono_class_setup_fields_locking (klass);
6971 /* in arrays, sizes.class_size is unioned with element_size
6972 * and arrays have no static fields
6976 return klass->sizes.class_size;
6980 * Auxiliary routine to mono_class_get_field
6982 * Takes a field index instead of a field token.
6984 static MonoClassField *
6985 mono_class_get_field_idx (MonoClass *klass, int idx)
6987 mono_class_setup_fields_locking (klass);
6988 if (mono_class_has_failure (klass))
6992 if (klass->image->uncompressed_metadata) {
6994 * klass->field.first points to the FieldPtr table, while idx points into the
6995 * Field table, so we have to do a search.
6997 /*FIXME this is broken for types with multiple fields with the same name.*/
6998 const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
7001 for (i = 0; i < klass->field.count; ++i)
7002 if (mono_field_get_name (&klass->fields [i]) == name)
7003 return &klass->fields [i];
7004 g_assert_not_reached ();
7006 if (klass->field.count) {
7007 if ((idx >= klass->field.first) && (idx < klass->field.first + klass->field.count)){
7008 return &klass->fields [idx - klass->field.first];
7012 klass = klass->parent;
7018 * mono_class_get_field:
7019 * @class: the class to lookup the field.
7020 * @field_token: the field token
7022 * Returns: A MonoClassField representing the type and offset of
7023 * the field, or a NULL value if the field does not belong to this
7027 mono_class_get_field (MonoClass *klass, guint32 field_token)
7029 int idx = mono_metadata_token_index (field_token);
7031 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
7033 return mono_class_get_field_idx (klass, idx - 1);
7037 * mono_class_get_field_from_name:
7038 * @klass: the class to lookup the field.
7039 * @name: the field name
7041 * Search the class @klass and it's parents for a field with the name @name.
7043 * Returns: The MonoClassField pointer of the named field or NULL
7046 mono_class_get_field_from_name (MonoClass *klass, const char *name)
7048 return mono_class_get_field_from_name_full (klass, name, NULL);
7052 * mono_class_get_field_from_name_full:
7053 * @klass: the class to lookup the field.
7054 * @name: the field name
7055 * @type: the type of the fields. This optional.
7057 * Search the class @klass and it's parents for a field with the name @name and type @type.
7059 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
7060 * of its generic type definition.
7062 * Returns: The MonoClassField pointer of the named field or NULL
7065 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
7069 mono_class_setup_fields_locking (klass);
7070 if (mono_class_has_failure (klass))
7074 for (i = 0; i < klass->field.count; ++i) {
7075 MonoClassField *field = &klass->fields [i];
7077 if (strcmp (name, mono_field_get_name (field)) != 0)
7081 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
7082 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
7087 klass = klass->parent;
7093 * mono_class_get_field_token:
7094 * @field: the field we need the token of
7096 * Get the token of a field. Note that the tokesn is only valid for the image
7097 * the field was loaded from. Don't use this function for fields in dynamic types.
7099 * Returns: The token representing the field in the image it was loaded from.
7102 mono_class_get_field_token (MonoClassField *field)
7104 MonoClass *klass = field->parent;
7107 mono_class_setup_fields_locking (klass);
7112 for (i = 0; i < klass->field.count; ++i) {
7113 if (&klass->fields [i] == field) {
7114 int idx = klass->field.first + i + 1;
7116 if (klass->image->uncompressed_metadata)
7117 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
7118 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
7121 klass = klass->parent;
7124 g_assert_not_reached ();
7129 mono_field_get_index (MonoClassField *field)
7131 int index = field - field->parent->fields;
7133 g_assert (index >= 0 && index < field->parent->field.count);
7139 * mono_class_get_field_default_value:
7141 * Return the default value of the field as a pointer into the metadata blob.
7144 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
7147 guint32 constant_cols [MONO_CONSTANT_SIZE];
7149 MonoClass *klass = field->parent;
7151 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7153 if (!klass->ext || !klass->ext->field_def_values) {
7154 MonoFieldDefaultValue *def_values;
7156 mono_class_alloc_ext (klass);
7158 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
7160 mono_image_lock (klass->image);
7161 mono_memory_barrier ();
7162 if (!klass->ext->field_def_values)
7163 klass->ext->field_def_values = def_values;
7164 mono_image_unlock (klass->image);
7167 field_index = mono_field_get_index (field);
7169 if (!klass->ext->field_def_values [field_index].data) {
7170 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7174 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7176 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7177 klass->ext->field_def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7178 klass->ext->field_def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7181 *def_type = klass->ext->field_def_values [field_index].def_type;
7182 return klass->ext->field_def_values [field_index].data;
7186 mono_property_get_index (MonoProperty *prop)
7188 int index = prop - prop->parent->ext->properties;
7190 g_assert (index >= 0 && index < prop->parent->ext->property.count);
7196 * mono_class_get_property_default_value:
7198 * Return the default value of the field as a pointer into the metadata blob.
7201 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7204 guint32 constant_cols [MONO_CONSTANT_SIZE];
7205 MonoClass *klass = property->parent;
7207 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7209 * We don't cache here because it is not used by C# so it's quite rare, but
7210 * we still do the lookup in klass->ext because that is where the data
7211 * is stored for dynamic assemblies.
7214 if (image_is_dynamic (klass->image)) {
7215 int prop_index = mono_property_get_index (property);
7216 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
7217 *def_type = klass->ext->prop_def_values [prop_index].def_type;
7218 return klass->ext->prop_def_values [prop_index].data;
7222 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7226 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7227 *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7228 return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7232 mono_class_get_event_token (MonoEvent *event)
7234 MonoClass *klass = event->parent;
7239 for (i = 0; i < klass->ext->event.count; ++i) {
7240 if (&klass->ext->events [i] == event)
7241 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
7244 klass = klass->parent;
7247 g_assert_not_reached ();
7252 * mono_class_get_property_from_name:
7254 * @name: name of the property to lookup in the specified class
7256 * Use this method to lookup a property in a class
7257 * Returns: the MonoProperty with the given name, or NULL if the property
7258 * does not exist on the @klass.
7261 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7265 gpointer iter = NULL;
7266 while ((p = mono_class_get_properties (klass, &iter))) {
7267 if (! strcmp (name, p->name))
7270 klass = klass->parent;
7276 * mono_class_get_property_token:
7277 * @prop: MonoProperty to query
7279 * Returns: The ECMA token for the specified property.
7282 mono_class_get_property_token (MonoProperty *prop)
7284 MonoClass *klass = prop->parent;
7288 gpointer iter = NULL;
7289 while ((p = mono_class_get_properties (klass, &iter))) {
7290 if (&klass->ext->properties [i] == prop)
7291 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
7295 klass = klass->parent;
7298 g_assert_not_reached ();
7303 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7305 const char *name, *nspace;
7306 if (image_is_dynamic (image))
7307 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7309 switch (type_token & 0xff000000){
7310 case MONO_TOKEN_TYPE_DEF: {
7311 guint32 cols [MONO_TYPEDEF_SIZE];
7312 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7313 guint tidx = mono_metadata_token_index (type_token);
7315 if (tidx > tt->rows)
7316 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7318 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7319 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7320 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7321 if (strlen (nspace) == 0)
7322 return g_strdup_printf ("%s", name);
7324 return g_strdup_printf ("%s.%s", nspace, name);
7327 case MONO_TOKEN_TYPE_REF: {
7329 guint32 cols [MONO_TYPEREF_SIZE];
7330 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7331 guint tidx = mono_metadata_token_index (type_token);
7334 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7336 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7337 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7338 mono_error_cleanup (&error);
7342 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7343 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7344 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7345 if (strlen (nspace) == 0)
7346 return g_strdup_printf ("%s", name);
7348 return g_strdup_printf ("%s.%s", nspace, name);
7351 case MONO_TOKEN_TYPE_SPEC:
7352 return g_strdup_printf ("Typespec 0x%08x", type_token);
7354 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7359 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7361 if (image_is_dynamic (image))
7362 return g_strdup_printf ("DynamicAssembly %s", image->name);
7364 switch (type_token & 0xff000000){
7365 case MONO_TOKEN_TYPE_DEF:
7366 if (image->assembly)
7367 return mono_stringify_assembly_name (&image->assembly->aname);
7368 else if (image->assembly_name)
7369 return g_strdup (image->assembly_name);
7370 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7371 case MONO_TOKEN_TYPE_REF: {
7373 MonoAssemblyName aname;
7374 guint32 cols [MONO_TYPEREF_SIZE];
7375 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7376 guint32 idx = mono_metadata_token_index (type_token);
7379 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7381 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7382 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7383 mono_error_cleanup (&error);
7386 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7388 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7389 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7390 case MONO_RESOLUTION_SCOPE_MODULE:
7392 return g_strdup ("");
7393 case MONO_RESOLUTION_SCOPE_MODULEREF:
7395 return g_strdup ("");
7396 case MONO_RESOLUTION_SCOPE_TYPEREF:
7398 return g_strdup ("");
7399 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7400 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7401 return mono_stringify_assembly_name (&aname);
7403 g_assert_not_reached ();
7407 case MONO_TOKEN_TYPE_SPEC:
7409 return g_strdup ("");
7411 g_assert_not_reached ();
7418 * mono_class_get_full:
7419 * @image: the image where the class resides
7420 * @type_token: the token for the class
7421 * @context: the generic context used to evaluate generic instantiations in
7422 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7424 * Returns: The MonoClass that represents @type_token in @image
7427 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7431 klass = mono_class_get_checked (image, type_token, &error);
7433 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7434 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7436 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7442 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7446 mono_error_init (error);
7447 klass = mono_class_get_checked (image, type_token, error);
7449 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7450 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7455 * mono_class_get_checked:
7456 * @image: the image where the class resides
7457 * @type_token: the token for the class
7458 * @error: error object to return any error
7460 * Returns: The MonoClass that represents @type_token in @image, or NULL on error.
7463 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7465 MonoClass *klass = NULL;
7467 mono_error_init (error);
7469 if (image_is_dynamic (image)) {
7470 int table = mono_metadata_token_table (type_token);
7472 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7473 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7476 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL); /*FIXME proper error handling*/
7480 switch (type_token & 0xff000000){
7481 case MONO_TOKEN_TYPE_DEF:
7482 klass = mono_class_create_from_typedef (image, type_token, error);
7484 case MONO_TOKEN_TYPE_REF:
7485 klass = mono_class_from_typeref_checked (image, type_token, error);
7487 case MONO_TOKEN_TYPE_SPEC:
7488 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7491 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7495 /* Generic case, should be avoided for when a better error is possible. */
7496 if (!klass && mono_error_ok (error)) {
7497 char *name = mono_class_name_from_token (image, type_token);
7498 char *assembly = mono_assembly_name_from_token (image, type_token);
7499 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7507 * mono_type_get_checked:
7508 * @image: the image where the type resides
7509 * @type_token: the token for the type
7510 * @context: the generic context used to evaluate generic instantiations in
7511 * @error: Error handling context
7513 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7515 * Returns: The MonoType that represents @type_token in @image
7518 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7520 MonoType *type = NULL;
7521 gboolean inflated = FALSE;
7523 mono_error_init (error);
7525 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7526 if (image_is_dynamic (image))
7527 return mono_class_get_type ((MonoClass *)mono_lookup_dynamic_token (image, type_token, context));
7529 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7530 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7533 mono_loader_assert_no_error ();
7538 return mono_class_get_type (klass);
7541 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7544 mono_loader_assert_no_error ();
7549 MonoType *tmp = type;
7550 type = mono_class_get_type (mono_class_from_mono_type (type));
7551 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7552 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7553 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7555 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7557 if (type->type != tmp->type)
7560 mono_metadata_free_type (tmp);
7567 * @image: image where the class token will be looked up.
7568 * @type_token: a type token from the image
7570 * Returns the MonoClass with the given @type_token on the @image
7573 mono_class_get (MonoImage *image, guint32 type_token)
7575 return mono_class_get_full (image, type_token, NULL);
7579 * mono_image_init_name_cache:
7581 * Initializes the class name cache stored in image->name_cache.
7583 * LOCKING: Acquires the corresponding image lock.
7586 mono_image_init_name_cache (MonoImage *image)
7588 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7589 guint32 cols [MONO_TYPEDEF_SIZE];
7592 guint32 i, visib, nspace_index;
7593 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7595 if (image->name_cache)
7598 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7600 if (image_is_dynamic (image)) {
7601 mono_image_lock (image);
7602 if (image->name_cache) {
7603 /* Somebody initialized it before us */
7604 g_hash_table_destroy (the_name_cache);
7606 mono_atomic_store_release (&image->name_cache, the_name_cache);
7608 mono_image_unlock (image);
7612 /* Temporary hash table to avoid lookups in the nspace_table */
7613 name_cache2 = g_hash_table_new (NULL, NULL);
7615 for (i = 1; i <= t->rows; ++i) {
7616 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7617 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7619 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7620 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7622 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7624 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7625 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7627 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7628 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7629 if (!nspace_table) {
7630 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7631 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7632 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7635 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7638 /* Load type names from EXPORTEDTYPES table */
7640 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7641 guint32 cols [MONO_EXP_TYPE_SIZE];
7644 for (i = 0; i < t->rows; ++i) {
7645 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7647 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7648 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7652 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7653 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7655 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7656 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7657 if (!nspace_table) {
7658 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7659 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7660 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7663 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7667 g_hash_table_destroy (name_cache2);
7669 mono_image_lock (image);
7670 if (image->name_cache) {
7671 /* Somebody initialized it before us */
7672 g_hash_table_destroy (the_name_cache);
7674 mono_atomic_store_release (&image->name_cache, the_name_cache);
7676 mono_image_unlock (image);
7679 /*FIXME Only dynamic assemblies should allow this operation.*/
7681 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7682 const char *name, guint32 index)
7684 GHashTable *nspace_table;
7685 GHashTable *name_cache;
7688 mono_image_init_name_cache (image);
7689 mono_image_lock (image);
7691 name_cache = image->name_cache;
7692 if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7693 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7694 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7697 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7698 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7700 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7702 mono_image_unlock (image);
7711 find_nocase (gpointer key, gpointer value, gpointer user_data)
7713 char *name = (char*)key;
7714 FindUserData *data = (FindUserData*)user_data;
7716 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7717 data->value = value;
7721 * mono_class_from_name_case:
7722 * @image: The MonoImage where the type is looked up in
7723 * @name_space: the type namespace
7724 * @name: the type short name.
7725 * @deprecated: use the mono_class_from_name_case_checked variant instead.
7727 * Obtains a MonoClass with a given namespace and a given name which
7728 * is located in the given MonoImage. The namespace and name
7729 * lookups are case insensitive.
7732 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7735 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7736 g_assert (!mono_error_ok (&error));
7741 * mono_class_from_name_case:
7742 * @image: The MonoImage where the type is looked up in
7743 * @name_space: the type namespace
7744 * @name: the type short name.
7747 * Obtains a MonoClass with a given namespace and a given name which
7748 * is located in the given MonoImage. The namespace and name
7749 * lookups are case insensitive.
7751 * Returns: The MonoClass if the given namespace and name were found, or NULL if it
7752 * was not found. The @error object will contain information about the problem
7756 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7758 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7759 guint32 cols [MONO_TYPEDEF_SIZE];
7764 mono_error_init (error);
7766 if (image_is_dynamic (image)) {
7768 FindUserData user_data;
7770 mono_image_init_name_cache (image);
7771 mono_image_lock (image);
7773 user_data.key = name_space;
7774 user_data.value = NULL;
7775 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7777 if (user_data.value) {
7778 GHashTable *nspace_table = (GHashTable*)user_data.value;
7780 user_data.key = name;
7781 user_data.value = NULL;
7783 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7785 if (user_data.value)
7786 token = GPOINTER_TO_UINT (user_data.value);
7789 mono_image_unlock (image);
7792 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7798 /* add a cache if needed */
7799 for (i = 1; i <= t->rows; ++i) {
7800 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7801 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7803 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7804 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7806 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7808 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7809 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7810 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7811 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7817 return_nested_in (MonoClass *klass, char *nested)
7820 char *s = strchr (nested, '/');
7821 gpointer iter = NULL;
7828 while ((found = mono_class_get_nested_types (klass, &iter))) {
7829 if (strcmp (found->name, nested) == 0) {
7831 return return_nested_in (found, s);
7839 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7841 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7842 MonoImage *file_image;
7846 mono_error_init (error);
7849 * The EXPORTEDTYPES table only contains public types, so have to search the
7851 * Note: image->modules contains the contents of the MODULEREF table, while
7852 * the real module list is in the FILE table.
7854 for (i = 0; i < file_table->rows; i++) {
7855 guint32 cols [MONO_FILE_SIZE];
7856 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7857 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7860 file_image = mono_image_load_file_for_image (image, i + 1);
7862 klass = mono_class_from_name_checked (file_image, name_space, name, error);
7863 if (klass || !is_ok (error))
7872 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7874 GHashTable *nspace_table;
7875 MonoImage *loaded_image;
7882 mono_error_init (error);
7884 // Checking visited images avoids stack overflows when cyclic references exist.
7885 if (g_hash_table_lookup (visited_images, image))
7888 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7890 if ((nested = strchr (name, '/'))) {
7891 int pos = nested - name;
7892 int len = strlen (name);
7895 memcpy (buf, name, len + 1);
7897 nested = buf + pos + 1;
7901 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7902 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7903 gboolean res = get_class_from_name (image, name_space, name, &klass);
7906 klass = search_modules (image, name_space, name, error);
7911 return klass ? return_nested_in (klass, nested) : NULL;
7917 mono_image_init_name_cache (image);
7918 mono_image_lock (image);
7920 nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7923 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7925 mono_image_unlock (image);
7927 if (!token && image_is_dynamic (image) && image->modules) {
7928 /* Search modules as well */
7929 for (i = 0; i < image->module_count; ++i) {
7930 MonoImage *module = image->modules [i];
7932 klass = mono_class_from_name_checked (module, name_space, name, error);
7933 if (klass || !is_ok (error))
7939 klass = search_modules (image, name_space, name, error);
7940 if (klass || !is_ok (error))
7947 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7948 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7949 guint32 cols [MONO_EXP_TYPE_SIZE];
7952 idx = mono_metadata_token_index (token);
7954 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7956 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7957 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7958 loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
7961 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7963 return klass ? return_nested_in (klass, nested) : NULL;
7965 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7966 guint32 assembly_idx;
7968 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7970 mono_assembly_load_reference (image, assembly_idx - 1);
7971 g_assert (image->references [assembly_idx - 1]);
7972 if (image->references [assembly_idx - 1] == (gpointer)-1)
7974 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
7976 return klass ? return_nested_in (klass, nested) : NULL;
7979 g_assert_not_reached ();
7983 token = MONO_TOKEN_TYPE_DEF | token;
7985 klass = mono_class_get_checked (image, token, error);
7987 return return_nested_in (klass, nested);
7992 * mono_class_from_name_checked:
7993 * @image: The MonoImage where the type is looked up in
7994 * @name_space: the type namespace
7995 * @name: the type short name.
7997 * Obtains a MonoClass with a given namespace and a given name which
7998 * is located in the given MonoImage.
8000 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
8001 * set if the class was not found or it will return NULL and set the error if there was a loading error.
8004 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
8007 GHashTable *visited_images;
8009 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
8011 klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
8013 g_hash_table_destroy (visited_images);
8019 * mono_class_from_name:
8020 * @image: The MonoImage where the type is looked up in
8021 * @name_space: the type namespace
8022 * @name: the type short name.
8024 * Obtains a MonoClass with a given namespace and a given name which
8025 * is located in the given MonoImage.
8027 * To reference nested classes, use the "/" character as a separator.
8028 * For example use "Foo/Bar" to reference the class Bar that is nested
8029 * inside Foo, like this: "class Foo { class Bar {} }".
8032 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
8037 klass = mono_class_from_name_checked (image, name_space, name, &error);
8038 if (!mono_error_ok (&error)) {
8039 mono_loader_set_error_from_mono_error (&error);
8040 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
8046 * mono_class_load_from_name:
8047 * @image: The MonoImage where the type is looked up in
8048 * @name_space: the type namespace
8049 * @name: the type short name.
8051 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
8052 * This function should be used by the runtime for critical types to which there's no way to recover but crash
8053 * If they are missing. Thing of System.Object or System.String.
8056 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
8061 klass = mono_class_from_name_checked (image, name_space, name, &error);
8063 g_error ("Runtime critical type %s.%s not found", name_space, name);
8064 if (!mono_error_ok (&error))
8065 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8070 * mono_class_try_load_from_name:
8071 * @image: The MonoImage where the type is looked up in
8072 * @name_space: the type namespace
8073 * @name: the type short name.
8075 * This function tries to load a type, returning the class was found or NULL otherwise.
8076 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
8078 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
8079 * a type that we would otherwise assume to be available but was not due some error.
8083 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
8088 klass = mono_class_from_name_checked (image, name_space, name, &error);
8089 if (!mono_error_ok (&error))
8090 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8096 * mono_class_is_subclass_of:
8097 * @klass: class to probe if it is a subclass of another one
8098 * @klassc: the class we suspect is the base class
8099 * @check_interfaces: whether we should perform interface checks
8101 * This method determines whether @klass is a subclass of @klassc.
8103 * If the @check_interfaces flag is set, then if @klassc is an interface
8104 * this method return TRUE if the @klass implements the interface or
8105 * if @klass is an interface, if one of its base classes is @klass.
8107 * If @check_interfaces is false then, then if @klass is not an interface
8108 * then it returns TRUE if the @klass is a subclass of @klassc.
8110 * if @klass is an interface and @klassc is System.Object, then this function
8115 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
8116 gboolean check_interfaces)
8118 /*FIXME test for interfaces with variant generic arguments*/
8120 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
8121 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
8123 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
8126 for (i = 0; i < klass->interface_count; i ++) {
8127 MonoClass *ic = klass->interfaces [i];
8132 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
8137 * MS.NET thinks interfaces are a subclass of Object, so we think it as
8140 if (klassc == mono_defaults.object_class)
8147 mono_type_is_generic_argument (MonoType *type)
8149 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
8153 mono_class_has_variant_generic_params (MonoClass *klass)
8156 MonoGenericContainer *container;
8158 if (!klass->generic_class)
8161 container = klass->generic_class->container_class->generic_container;
8163 for (i = 0; i < container->type_argc; ++i)
8164 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8171 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8173 if (target == candidate)
8176 if (check_for_reference_conv &&
8177 mono_type_is_generic_argument (&target->byval_arg) &&
8178 mono_type_is_generic_argument (&candidate->byval_arg)) {
8179 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8180 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8182 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8185 if (!mono_class_is_assignable_from (target, candidate))
8191 * @container the generic container from the GTD
8192 * @klass: the class to be assigned to
8193 * @oklass: the source class
8195 * Both @klass and @oklass must be instances of the same generic interface.
8197 * Returns: TRUE if @klass can be assigned to a @klass variable
8200 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8203 MonoType **klass_argv, **oklass_argv;
8204 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8205 MonoGenericContainer *container = klass_gtd->generic_container;
8207 if (klass == oklass)
8210 /*Viable candidates are instances of the same generic interface*/
8211 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8214 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8215 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8217 for (j = 0; j < container->type_argc; ++j) {
8218 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8219 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8221 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8225 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8226 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8228 if (param1_class != param2_class) {
8229 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8230 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8232 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8233 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8243 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8245 MonoGenericParam *gparam, *ogparam;
8246 MonoGenericParamInfo *tinfo, *cinfo;
8247 MonoClass **candidate_class;
8248 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8251 if (target == candidate)
8253 if (target->byval_arg.type != candidate->byval_arg.type)
8256 gparam = target->byval_arg.data.generic_param;
8257 ogparam = candidate->byval_arg.data.generic_param;
8258 tinfo = mono_generic_param_info (gparam);
8259 cinfo = mono_generic_param_info (ogparam);
8261 class_constraint_satisfied = FALSE;
8262 valuetype_constraint_satisfied = FALSE;
8264 /*candidate must have a super set of target's special constraints*/
8265 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8266 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8268 if (cinfo->constraints) {
8269 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8270 MonoClass *cc = *candidate_class;
8272 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8273 class_constraint_satisfied = TRUE;
8274 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8275 valuetype_constraint_satisfied = TRUE;
8278 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8279 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8281 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8283 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8285 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8286 valuetype_constraint_satisfied)) {
8291 /*candidate type constraints must be a superset of target's*/
8292 if (tinfo->constraints) {
8293 MonoClass **target_class;
8294 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8295 MonoClass *tc = *target_class;
8298 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8299 * check it's constraints since it satisfy the constraint by itself.
8301 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8304 if (!cinfo->constraints)
8307 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8308 MonoClass *cc = *candidate_class;
8310 if (mono_class_is_assignable_from (tc, cc))
8314 * This happens when we have the following:
8316 * Bar<K> where K : IFace
8317 * Foo<T, U> where T : U where U : IFace
8319 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8322 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8323 if (mono_gparam_is_assignable_from (target, cc))
8327 if (!*candidate_class)
8332 /*candidate itself must have a constraint that satisfy target*/
8333 if (cinfo->constraints) {
8334 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8335 MonoClass *cc = *candidate_class;
8336 if (mono_class_is_assignable_from (target, cc))
8344 * mono_class_is_assignable_from:
8345 * @klass: the class to be assigned to
8346 * @oklass: the source class
8348 * Returns: TRUE if an instance of object oklass can be assigned to an
8349 * instance of object @klass
8352 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8354 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8356 mono_class_init (klass);
8358 if (!oklass->inited)
8359 mono_class_init (oklass);
8361 if (mono_class_has_failure (klass) || mono_class_has_failure (oklass))
8364 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8365 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8367 return mono_gparam_is_assignable_from (klass, oklass);
8370 if (MONO_CLASS_IS_INTERFACE (klass)) {
8371 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8372 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8373 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8377 for (i = 0; constraints [i]; ++i) {
8378 if (mono_class_is_assignable_from (klass, constraints [i]))
8386 /* interface_offsets might not be set for dynamic classes */
8387 if (oklass->ref_info_handle && !oklass->interface_bitmap)
8389 * oklass might be a generic type parameter but they have
8390 * interface_offsets set.
8392 return mono_reflection_call_is_assignable_to (oklass, klass);
8393 if (!oklass->interface_bitmap)
8394 /* Happens with generic instances of not-yet created dynamic types */
8396 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8399 if (mono_class_has_variant_generic_params (klass)) {
8402 mono_class_setup_interfaces (oklass, &error);
8403 if (!mono_error_ok (&error)) {
8404 mono_error_cleanup (&error);
8408 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8409 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8410 MonoClass *iface = oklass->interfaces_packed [i];
8412 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8417 } else if (klass->delegate) {
8418 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8420 }else if (klass->rank) {
8421 MonoClass *eclass, *eoclass;
8423 if (oklass->rank != klass->rank)
8426 /* vectors vs. one dimensional arrays */
8427 if (oklass->byval_arg.type != klass->byval_arg.type)
8430 eclass = klass->cast_class;
8431 eoclass = oklass->cast_class;
8434 * a is b does not imply a[] is b[] when a is a valuetype, and
8435 * b is a reference type.
8438 if (eoclass->valuetype) {
8439 if ((eclass == mono_defaults.enum_class) ||
8440 (eclass == mono_defaults.enum_class->parent) ||
8441 (eclass == mono_defaults.object_class))
8445 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8446 } else if (mono_class_is_nullable (klass)) {
8447 if (mono_class_is_nullable (oklass))
8448 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8450 return mono_class_is_assignable_from (klass->cast_class, oklass);
8451 } else if (klass == mono_defaults.object_class)
8454 return mono_class_has_parent (oklass, klass);
8457 /*Check if @oklass is variant compatible with @klass.*/
8459 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8462 MonoType **klass_argv, **oklass_argv;
8463 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8464 MonoGenericContainer *container = klass_gtd->generic_container;
8466 /*Viable candidates are instances of the same generic interface*/
8467 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8470 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8471 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8473 for (j = 0; j < container->type_argc; ++j) {
8474 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8475 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8477 if (param1_class->valuetype != param2_class->valuetype)
8481 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8482 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8484 if (param1_class != param2_class) {
8485 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8486 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8488 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8489 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8497 /*Check if @candidate implements the interface @target*/
8499 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8503 gboolean is_variant = mono_class_has_variant_generic_params (target);
8505 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8506 if (mono_class_is_variant_compatible_slow (target, candidate))
8511 if (candidate == target)
8514 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8515 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8516 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (candidate);
8518 if (tb && tb->interfaces) {
8519 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8520 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8521 MonoClass *iface_class;
8523 /* we can't realize the type here since it can do pretty much anything. */
8526 iface_class = mono_class_from_mono_type (iface->type);
8527 if (iface_class == target)
8529 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8531 if (mono_class_implement_interface_slow (target, iface_class))
8536 /*setup_interfaces don't mono_class_init anything*/
8537 /*FIXME this doesn't handle primitive type arrays.
8538 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8539 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8541 mono_class_setup_interfaces (candidate, &error);
8542 if (!mono_error_ok (&error)) {
8543 mono_error_cleanup (&error);
8547 for (i = 0; i < candidate->interface_count; ++i) {
8548 if (candidate->interfaces [i] == target)
8551 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8554 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8558 candidate = candidate->parent;
8559 } while (candidate);
8565 * Check if @oklass can be assigned to @klass.
8566 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8569 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8571 if (candidate == target)
8573 if (target == mono_defaults.object_class)
8576 if (mono_class_has_parent (candidate, target))
8579 /*If target is not an interface there is no need to check them.*/
8580 if (MONO_CLASS_IS_INTERFACE (target))
8581 return mono_class_implement_interface_slow (target, candidate);
8583 if (target->delegate && mono_class_has_variant_generic_params (target))
8584 return mono_class_is_variant_compatible (target, candidate, FALSE);
8587 MonoClass *eclass, *eoclass;
8589 if (target->rank != candidate->rank)
8592 /* vectors vs. one dimensional arrays */
8593 if (target->byval_arg.type != candidate->byval_arg.type)
8596 eclass = target->cast_class;
8597 eoclass = candidate->cast_class;
8600 * a is b does not imply a[] is b[] when a is a valuetype, and
8601 * b is a reference type.
8604 if (eoclass->valuetype) {
8605 if ((eclass == mono_defaults.enum_class) ||
8606 (eclass == mono_defaults.enum_class->parent) ||
8607 (eclass == mono_defaults.object_class))
8611 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8613 /*FIXME properly handle nullables */
8614 /*FIXME properly handle (M)VAR */
8619 * mono_class_get_cctor:
8620 * @klass: A MonoClass pointer
8622 * Returns: The static constructor of @klass if it exists, NULL otherwise.
8625 mono_class_get_cctor (MonoClass *klass)
8627 MonoCachedClassInfo cached_info;
8629 if (image_is_dynamic (klass->image)) {
8631 * has_cctor is not set for these classes because mono_class_init () is
8634 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8637 if (!klass->has_cctor)
8640 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8642 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8643 if (!mono_error_ok (&error))
8644 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8648 if (klass->generic_class && !klass->methods)
8649 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8651 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8655 * mono_class_get_finalizer:
8656 * @klass: The MonoClass pointer
8658 * Returns: The finalizer method of @klass if it exists, NULL otherwise.
8661 mono_class_get_finalizer (MonoClass *klass)
8663 MonoCachedClassInfo cached_info;
8666 mono_class_init (klass);
8667 if (!mono_class_has_finalizer (klass))
8670 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8672 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8673 if (!mono_error_ok (&error))
8674 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8677 mono_class_setup_vtable (klass);
8678 return klass->vtable [finalize_slot];
8683 * mono_class_needs_cctor_run:
8684 * @klass: the MonoClass pointer
8685 * @caller: a MonoMethod describing the caller
8687 * Determines whenever the class has a static constructor and whenever it
8688 * needs to be called when executing CALLER.
8691 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8695 method = mono_class_get_cctor (klass);
8697 return (method == caller) ? FALSE : TRUE;
8703 * mono_class_array_element_size:
8706 * Returns: The number of bytes an element of type @klass
8707 * uses when stored into an array.
8710 mono_class_array_element_size (MonoClass *klass)
8712 MonoType *type = &klass->byval_arg;
8715 switch (type->type) {
8718 case MONO_TYPE_BOOLEAN:
8722 case MONO_TYPE_CHAR:
8731 case MONO_TYPE_CLASS:
8732 case MONO_TYPE_STRING:
8733 case MONO_TYPE_OBJECT:
8734 case MONO_TYPE_SZARRAY:
8735 case MONO_TYPE_ARRAY:
8736 return sizeof (gpointer);
8741 case MONO_TYPE_VALUETYPE:
8742 if (type->data.klass->enumtype) {
8743 type = mono_class_enum_basetype (type->data.klass);
8744 klass = klass->element_class;
8747 return mono_class_instance_size (klass) - sizeof (MonoObject);
8748 case MONO_TYPE_GENERICINST:
8749 type = &type->data.generic_class->container_class->byval_arg;
8752 case MONO_TYPE_MVAR: {
8755 return mono_type_size (type, &align);
8757 case MONO_TYPE_VOID:
8761 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8767 * mono_array_element_size:
8768 * @ac: pointer to a #MonoArrayClass
8770 * Returns: The size of single array element.
8773 mono_array_element_size (MonoClass *ac)
8775 g_assert (ac->rank);
8776 return ac->sizes.element_size;
8780 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8781 MonoGenericContext *context)
8784 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8785 g_assert (mono_error_ok (&error));
8790 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8791 MonoGenericContext *context, MonoError *error)
8793 mono_error_init (error);
8795 if (image_is_dynamic (image)) {
8796 MonoClass *tmp_handle_class;
8797 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context);
8799 g_assert (tmp_handle_class);
8801 *handle_class = tmp_handle_class;
8803 if (tmp_handle_class == mono_defaults.typehandle_class)
8804 return &((MonoClass*)obj)->byval_arg;
8809 switch (token & 0xff000000) {
8810 case MONO_TOKEN_TYPE_DEF:
8811 case MONO_TOKEN_TYPE_REF:
8812 case MONO_TOKEN_TYPE_SPEC: {
8815 *handle_class = mono_defaults.typehandle_class;
8816 type = mono_type_get_checked (image, token, context, error);
8820 mono_class_init (mono_class_from_mono_type (type));
8821 /* We return a MonoType* as handle */
8824 case MONO_TOKEN_FIELD_DEF: {
8826 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8828 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8832 *handle_class = mono_defaults.fieldhandle_class;
8833 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8837 mono_class_init (klass);
8838 return mono_class_get_field (klass, token);
8840 case MONO_TOKEN_METHOD_DEF:
8841 case MONO_TOKEN_METHOD_SPEC: {
8843 meth = mono_get_method_checked (image, token, NULL, context, error);
8845 *handle_class = mono_defaults.methodhandle_class;
8851 case MONO_TOKEN_MEMBER_REF: {
8852 guint32 cols [MONO_MEMBERREF_SIZE];
8854 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8855 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8856 mono_metadata_decode_blob_size (sig, &sig);
8857 if (*sig == 0x6) { /* it's a field */
8859 MonoClassField *field;
8860 field = mono_field_from_token_checked (image, token, &klass, context, error);
8862 *handle_class = mono_defaults.fieldhandle_class;
8866 meth = mono_get_method_checked (image, token, NULL, context, error);
8868 *handle_class = mono_defaults.methodhandle_class;
8873 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8879 * This function might need to call runtime functions so it can't be part
8880 * of the metadata library.
8882 static MonoLookupDynamicToken lookup_dynamic = NULL;
8885 mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
8887 lookup_dynamic = func;
8891 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context)
8893 MonoClass *handle_class;
8895 return lookup_dynamic (image, token, TRUE, &handle_class, context);
8899 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
8901 return lookup_dynamic (image, token, valid_token, handle_class, context);
8904 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8907 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8909 get_cached_class_info = func;
8913 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8915 if (!get_cached_class_info)
8918 return get_cached_class_info (klass, res);
8922 mono_install_get_class_from_name (MonoGetClassFromName func)
8924 get_class_from_name = func;
8928 * mono_class_get_image:
8930 * Use this method to get the `MonoImage*` where this class came from.
8932 * Returns: The image where this class is defined.
8935 mono_class_get_image (MonoClass *klass)
8937 return klass->image;
8941 * mono_class_get_element_class:
8942 * @klass: the MonoClass to act on
8944 * Use this function to get the element class of an array.
8946 * Returns: The element class of an array.
8949 mono_class_get_element_class (MonoClass *klass)
8951 return klass->element_class;
8955 * mono_class_is_valuetype:
8956 * @klass: the MonoClass to act on
8958 * Use this method to determine if the provided `MonoClass*` represents a value type,
8959 * or a reference type.
8961 * Returns: TRUE if the MonoClass represents a ValueType, FALSE if it represents a reference type.
8964 mono_class_is_valuetype (MonoClass *klass)
8966 return klass->valuetype;
8970 * mono_class_is_enum:
8971 * @klass: the MonoClass to act on
8973 * Use this function to determine if the provided `MonoClass*` represents an enumeration.
8975 * Returns: TRUE if the MonoClass represents an enumeration.
8978 mono_class_is_enum (MonoClass *klass)
8980 return klass->enumtype;
8984 * mono_class_enum_basetype:
8985 * @klass: the MonoClass to act on
8987 * Use this function to get the underlying type for an enumeration value.
8989 * Returns: The underlying type representation for an enumeration.
8992 mono_class_enum_basetype (MonoClass *klass)
8994 if (klass->element_class == klass)
8995 /* SRE or broken types */
8998 return &klass->element_class->byval_arg;
9002 * mono_class_get_parent
9003 * @klass: the MonoClass to act on
9005 * Returns: The parent class for this class.
9008 mono_class_get_parent (MonoClass *klass)
9010 return klass->parent;
9014 * mono_class_get_nesting_type:
9015 * @klass: the MonoClass to act on
9017 * Use this function to obtain the class that the provided `MonoClass*` is nested on.
9019 * If the return is NULL, this indicates that this class is not nested.
9021 * Returns: The container type where this type is nested or NULL if this type is not a nested type.
9024 mono_class_get_nesting_type (MonoClass *klass)
9026 return klass->nested_in;
9030 * mono_class_get_rank:
9031 * @klass: the MonoClass to act on
9033 * Returns: The rank for the array (the number of dimensions).
9036 mono_class_get_rank (MonoClass *klass)
9042 * mono_class_get_flags:
9043 * @klass: the MonoClass to act on
9045 * The type flags from the TypeDef table from the metadata.
9046 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
9049 * Returns: The flags from the TypeDef table.
9052 mono_class_get_flags (MonoClass *klass)
9054 return klass->flags;
9058 * mono_class_get_name
9059 * @klass: the MonoClass to act on
9061 * Returns: The name of the class.
9064 mono_class_get_name (MonoClass *klass)
9070 * mono_class_get_namespace:
9071 * @klass: the MonoClass to act on
9073 * Returns: The namespace of the class.
9076 mono_class_get_namespace (MonoClass *klass)
9078 return klass->name_space;
9082 * mono_class_get_type:
9083 * @klass: the MonoClass to act on
9085 * This method returns the internal Type representation for the class.
9087 * Returns: The MonoType from the class.
9090 mono_class_get_type (MonoClass *klass)
9092 return &klass->byval_arg;
9096 * mono_class_get_type_token:
9097 * @klass: the MonoClass to act on
9099 * This method returns type token for the class.
9101 * Returns: The type token for the class.
9104 mono_class_get_type_token (MonoClass *klass)
9106 return klass->type_token;
9110 * mono_class_get_byref_type:
9111 * @klass: the MonoClass to act on
9116 mono_class_get_byref_type (MonoClass *klass)
9118 return &klass->this_arg;
9122 * mono_class_num_fields:
9123 * @klass: the MonoClass to act on
9125 * Returns: The number of static and instance fields in the class.
9128 mono_class_num_fields (MonoClass *klass)
9130 return klass->field.count;
9134 * mono_class_num_methods:
9135 * @klass: the MonoClass to act on
9137 * Returns: The number of methods in the class.
9140 mono_class_num_methods (MonoClass *klass)
9142 return klass->method.count;
9146 * mono_class_num_properties
9147 * @klass: the MonoClass to act on
9149 * Returns: The number of properties in the class.
9152 mono_class_num_properties (MonoClass *klass)
9154 mono_class_setup_properties (klass);
9156 return klass->ext->property.count;
9160 * mono_class_num_events:
9161 * @klass: the MonoClass to act on
9163 * Returns: The number of events in the class.
9166 mono_class_num_events (MonoClass *klass)
9168 mono_class_setup_events (klass);
9170 return klass->ext->event.count;
9174 * mono_class_get_fields:
9175 * @klass: the MonoClass to act on
9177 * This routine is an iterator routine for retrieving the fields in a class.
9179 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9180 * iterate over all of the elements. When no more values are
9181 * available, the return value is NULL.
9183 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
9186 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9188 MonoClassField* field;
9192 mono_class_setup_fields_locking (klass);
9193 if (mono_class_has_failure (klass))
9195 /* start from the first */
9196 if (klass->field.count) {
9197 *iter = &klass->fields [0];
9198 return &klass->fields [0];
9204 field = (MonoClassField *)*iter;
9206 if (field < &klass->fields [klass->field.count]) {
9214 * mono_class_get_methods
9215 * @klass: the MonoClass to act on
9217 * This routine is an iterator routine for retrieving the fields in a class.
9219 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9220 * iterate over all of the elements. When no more values are
9221 * available, the return value is NULL.
9223 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
9226 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9228 MonoMethod** method;
9232 mono_class_setup_methods (klass);
9235 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9236 * FIXME we should better report this error to the caller
9238 if (!klass->methods)
9240 /* start from the first */
9241 if (klass->method.count) {
9242 *iter = &klass->methods [0];
9243 return klass->methods [0];
9249 method = (MonoMethod **)*iter;
9251 if (method < &klass->methods [klass->method.count]) {
9259 * mono_class_get_virtual_methods:
9261 * Iterate over the virtual methods of KLASS.
9263 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9266 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9268 MonoMethod** method;
9271 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9273 mono_class_setup_methods (klass);
9275 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9276 * FIXME we should better report this error to the caller
9278 if (!klass->methods)
9280 /* start from the first */
9281 method = &klass->methods [0];
9283 method = (MonoMethod **)*iter;
9286 while (method < &klass->methods [klass->method.count]) {
9287 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9291 if (method < &klass->methods [klass->method.count]) {
9298 /* Search directly in metadata to avoid calling setup_methods () */
9299 MonoMethod *res = NULL;
9305 start_index = GPOINTER_TO_UINT (*iter);
9308 for (i = start_index; i < klass->method.count; ++i) {
9311 /* klass->method.first points into the methodptr table */
9312 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
9314 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9318 if (i < klass->method.count) {
9320 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9321 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9323 /* Add 1 here so the if (*iter) check fails */
9324 *iter = GUINT_TO_POINTER (i + 1);
9333 * mono_class_get_properties:
9334 * @klass: the MonoClass to act on
9336 * This routine is an iterator routine for retrieving the properties in a class.
9338 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9339 * iterate over all of the elements. When no more values are
9340 * available, the return value is NULL.
9342 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9345 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9347 MonoProperty* property;
9351 mono_class_setup_properties (klass);
9352 /* start from the first */
9353 if (klass->ext->property.count) {
9354 *iter = &klass->ext->properties [0];
9355 return (MonoProperty *)*iter;
9361 property = (MonoProperty *)*iter;
9363 if (property < &klass->ext->properties [klass->ext->property.count]) {
9365 return (MonoProperty *)*iter;
9371 * mono_class_get_events:
9372 * @klass: the MonoClass to act on
9374 * This routine is an iterator routine for retrieving the properties in a class.
9376 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9377 * iterate over all of the elements. When no more values are
9378 * available, the return value is NULL.
9380 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9383 mono_class_get_events (MonoClass* klass, gpointer *iter)
9389 mono_class_setup_events (klass);
9390 /* start from the first */
9391 if (klass->ext->event.count) {
9392 *iter = &klass->ext->events [0];
9393 return (MonoEvent *)*iter;
9399 event = (MonoEvent *)*iter;
9401 if (event < &klass->ext->events [klass->ext->event.count]) {
9403 return (MonoEvent *)*iter;
9409 * mono_class_get_interfaces
9410 * @klass: the MonoClass to act on
9412 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9414 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9415 * iterate over all of the elements. When no more values are
9416 * available, the return value is NULL.
9418 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9421 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9429 mono_class_init (klass);
9430 if (!klass->interfaces_inited) {
9431 mono_class_setup_interfaces (klass, &error);
9432 if (!mono_error_ok (&error)) {
9433 mono_error_cleanup (&error);
9437 /* start from the first */
9438 if (klass->interface_count) {
9439 *iter = &klass->interfaces [0];
9440 return klass->interfaces [0];
9446 iface = (MonoClass **)*iter;
9448 if (iface < &klass->interfaces [klass->interface_count]) {
9456 setup_nested_types (MonoClass *klass)
9459 GList *classes, *nested_classes, *l;
9462 if (klass->nested_classes_inited)
9465 if (!klass->type_token)
9466 klass->nested_classes_inited = TRUE;
9468 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9472 guint32 cols [MONO_NESTED_CLASS_SIZE];
9473 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9474 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9475 if (!mono_error_ok (&error)) {
9476 /*FIXME don't swallow the error message*/
9477 mono_error_cleanup (&error);
9479 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9483 classes = g_list_prepend (classes, nclass);
9485 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9488 mono_class_alloc_ext (klass);
9490 nested_classes = NULL;
9491 for (l = classes; l; l = l->next)
9492 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9493 g_list_free (classes);
9495 mono_image_lock (klass->image);
9497 mono_memory_barrier ();
9498 if (!klass->nested_classes_inited) {
9499 klass->ext->nested_classes = nested_classes;
9500 mono_memory_barrier ();
9501 klass->nested_classes_inited = TRUE;
9504 mono_image_unlock (klass->image);
9508 * mono_class_get_nested_types
9509 * @klass: the MonoClass to act on
9511 * This routine is an iterator routine for retrieving the nested types of a class.
9512 * This works only if @klass is non-generic, or a generic type definition.
9514 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9515 * iterate over all of the elements. When no more values are
9516 * available, the return value is NULL.
9518 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9521 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9527 if (!klass->nested_classes_inited)
9528 setup_nested_types (klass);
9531 /* start from the first */
9532 if (klass->ext && klass->ext->nested_classes) {
9533 *iter = klass->ext->nested_classes;
9534 return (MonoClass *)klass->ext->nested_classes->data;
9536 /* no nested types */
9540 item = (GList *)*iter;
9544 return (MonoClass *)item->data;
9551 * mono_class_is_delegate
9552 * @klass: the MonoClass to act on
9554 * Returns: TRUE if the MonoClass represents a System.Delegate.
9557 mono_class_is_delegate (MonoClass *klass)
9559 return klass->delegate;
9563 * mono_class_implements_interface
9564 * @klass: The MonoClass to act on
9565 * @interface: The interface to check if @klass implements.
9567 * Returns: TRUE if @klass implements @interface.
9570 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9572 return mono_class_is_assignable_from (iface, klass);
9576 * mono_field_get_name:
9577 * @field: the MonoClassField to act on
9579 * Returns: The name of the field.
9582 mono_field_get_name (MonoClassField *field)
9588 * mono_field_get_type:
9589 * @field: the MonoClassField to act on
9591 * Returns: MonoType of the field.
9594 mono_field_get_type (MonoClassField *field)
9597 MonoType *type = mono_field_get_type_checked (field, &error);
9598 if (!mono_error_ok (&error)) {
9599 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9600 mono_error_cleanup (&error);
9607 * mono_field_get_type_checked:
9608 * @field: the MonoClassField to act on
9609 * @error: used to return any erro found while retrieving @field type
9611 * Returns: MonoType of the field.
9614 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9616 mono_error_init (error);
9618 mono_field_resolve_type (field, error);
9623 * mono_field_get_parent:
9624 * @field: the MonoClassField to act on
9626 * Returns: MonoClass where the field was defined.
9629 mono_field_get_parent (MonoClassField *field)
9631 return field->parent;
9635 * mono_field_get_flags;
9636 * @field: the MonoClassField to act on
9638 * The metadata flags for a field are encoded using the
9639 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9641 * Returns: The flags for the field.
9644 mono_field_get_flags (MonoClassField *field)
9647 return mono_field_resolve_flags (field);
9648 return field->type->attrs;
9652 * mono_field_get_offset:
9653 * @field: the MonoClassField to act on
9655 * Returns: The field offset.
9658 mono_field_get_offset (MonoClassField *field)
9660 return field->offset;
9664 mono_field_get_rva (MonoClassField *field)
9668 MonoClass *klass = field->parent;
9669 MonoFieldDefaultValue *field_def_values;
9671 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9673 if (!klass->ext || !klass->ext->field_def_values) {
9674 mono_class_alloc_ext (klass);
9676 field_def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9678 mono_image_lock (klass->image);
9679 if (!klass->ext->field_def_values)
9680 klass->ext->field_def_values = field_def_values;
9681 mono_image_unlock (klass->image);
9684 field_index = mono_field_get_index (field);
9686 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9687 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9689 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9690 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9693 return klass->ext->field_def_values [field_index].data;
9697 * mono_field_get_data:
9698 * @field: the MonoClassField to act on
9700 * Returns: A pointer to the metadata constant value or to the field
9701 * data if it has an RVA flag.
9704 mono_field_get_data (MonoClassField *field)
9706 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9707 MonoTypeEnum def_type;
9709 return mono_class_get_field_default_value (field, &def_type);
9710 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9711 return mono_field_get_rva (field);
9718 * mono_property_get_name:
9719 * @prop: the MonoProperty to act on
9721 * Returns: The name of the property
9724 mono_property_get_name (MonoProperty *prop)
9730 * mono_property_get_set_method
9731 * @prop: the MonoProperty to act on.
9733 * Returns: The setter method of the property (A MonoMethod)
9736 mono_property_get_set_method (MonoProperty *prop)
9742 * mono_property_get_get_method
9743 * @prop: the MonoProperty to act on.
9745 * Returns: The setter method of the property (A MonoMethod)
9748 mono_property_get_get_method (MonoProperty *prop)
9754 * mono_property_get_parent:
9755 * @prop: the MonoProperty to act on.
9757 * Returns: The MonoClass where the property was defined.
9760 mono_property_get_parent (MonoProperty *prop)
9762 return prop->parent;
9766 * mono_property_get_flags:
9767 * @prop: the MonoProperty to act on.
9769 * The metadata flags for a property are encoded using the
9770 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9772 * Returns: The flags for the property.
9775 mono_property_get_flags (MonoProperty *prop)
9781 * mono_event_get_name:
9782 * @event: the MonoEvent to act on
9784 * Returns: The name of the event.
9787 mono_event_get_name (MonoEvent *event)
9793 * mono_event_get_add_method:
9794 * @event: The MonoEvent to act on.
9796 * Returns: The @add' method for the event (a MonoMethod).
9799 mono_event_get_add_method (MonoEvent *event)
9805 * mono_event_get_remove_method:
9806 * @event: The MonoEvent to act on.
9808 * Returns: The @remove method for the event (a MonoMethod).
9811 mono_event_get_remove_method (MonoEvent *event)
9813 return event->remove;
9817 * mono_event_get_raise_method:
9818 * @event: The MonoEvent to act on.
9820 * Returns: The @raise method for the event (a MonoMethod).
9823 mono_event_get_raise_method (MonoEvent *event)
9825 return event->raise;
9829 * mono_event_get_parent:
9830 * @event: the MonoEvent to act on.
9832 * Returns: The MonoClass where the event is defined.
9835 mono_event_get_parent (MonoEvent *event)
9837 return event->parent;
9841 * mono_event_get_flags
9842 * @event: the MonoEvent to act on.
9844 * The metadata flags for an event are encoded using the
9845 * EVENT_* constants. See the tabledefs.h file for details.
9847 * Returns: The flags for the event.
9850 mono_event_get_flags (MonoEvent *event)
9852 return event->attrs;
9856 * mono_class_get_method_from_name:
9857 * @klass: where to look for the method
9858 * @name: name of the method
9859 * @param_count: number of parameters. -1 for any number.
9861 * Obtains a MonoMethod with a given name and number of parameters.
9862 * It only works if there are no multiple signatures for any given method name.
9865 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9867 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9871 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9873 MonoMethod *res = NULL;
9876 /* Search directly in the metadata to avoid calling setup_methods () */
9877 for (i = 0; i < klass->method.count; ++i) {
9879 guint32 cols [MONO_METHOD_SIZE];
9881 MonoMethodSignature *sig;
9883 /* klass->method.first points into the methodptr table */
9884 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9886 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9887 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9889 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9892 if (param_count == -1) {
9896 sig = mono_method_signature_checked (method, &error);
9898 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9901 if (sig->param_count == param_count) {
9912 * mono_class_get_method_from_name_flags:
9913 * @klass: where to look for the method
9914 * @name_space: name of the method
9915 * @param_count: number of parameters. -1 for any number.
9916 * @flags: flags which must be set in the method
9918 * Obtains a MonoMethod with a given name and number of parameters.
9919 * It only works if there are no multiple signatures for any given method name.
9922 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9924 MonoMethod *res = NULL;
9927 mono_class_init (klass);
9929 if (klass->generic_class && !klass->methods) {
9930 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9933 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9934 if (!mono_error_ok (&error))
9935 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9940 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9941 mono_class_setup_methods (klass);
9943 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9944 See mono/tests/array_load_exception.il
9945 FIXME we should better report this error to the caller
9947 if (!klass->methods)
9949 for (i = 0; i < klass->method.count; ++i) {
9950 MonoMethod *method = klass->methods [i];
9952 if (method->name[0] == name [0] &&
9953 !strcmp (name, method->name) &&
9954 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9955 ((method->flags & flags) == flags)) {
9962 res = find_method_in_metadata (klass, name, param_count, flags);
9969 * mono_class_set_failure:
9970 * @klass: class in which the failure was detected
9971 * @ex_type: the kind of exception/error to be thrown (later)
9972 * @ex_data: exception data (specific to each type of exception/error)
9974 * Keep a detected failure informations in the class for later processing.
9975 * Note that only the first failure is kept.
9977 * LOCKING: Acquires the loader lock.
9980 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9982 if (mono_class_has_failure (klass))
9985 mono_loader_lock ();
9986 klass->exception_type = ex_type;
9988 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9989 mono_loader_unlock ();
9995 * mono_class_get_exception_data:
9997 * Return the exception_data property of KLASS.
9999 * LOCKING: Acquires the loader lock.
10002 mono_class_get_exception_data (MonoClass *klass)
10004 return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
10008 * mono_classes_init:
10010 * Initialize the resources used by this module.
10013 mono_classes_init (void)
10015 mono_os_mutex_init (&classes_mutex);
10017 mono_counters_register ("Inflated methods size",
10018 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
10019 mono_counters_register ("Inflated classes",
10020 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
10021 mono_counters_register ("Inflated classes size",
10022 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
10023 mono_counters_register ("MonoClass size",
10024 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
10025 mono_counters_register ("MonoClassExt size",
10026 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
10030 * mono_classes_cleanup:
10032 * Free the resources used by this module.
10035 mono_classes_cleanup (void)
10037 if (global_interface_bitset)
10038 mono_bitset_free (global_interface_bitset);
10039 global_interface_bitset = NULL;
10040 mono_os_mutex_destroy (&classes_mutex);
10044 * mono_class_get_exception_for_failure:
10045 * @klass: class in which the failure was detected
10047 * Return a constructed MonoException than the caller can then throw
10048 * using mono_raise_exception - or NULL if no failure is present (or
10049 * doesn't result in an exception).
10052 mono_class_get_exception_for_failure (MonoClass *klass)
10054 gpointer exception_data = mono_class_get_exception_data (klass);
10056 switch (mono_class_get_failure(klass)) {
10057 case MONO_EXCEPTION_TYPE_LOAD: {
10060 char *str = mono_type_get_full_name (klass);
10061 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
10062 name = mono_string_new (mono_domain_get (), str);
10064 ex = mono_get_exception_type_load (name, astr);
10068 case MONO_EXCEPTION_MISSING_METHOD: {
10069 char *class_name = (char *)exception_data;
10070 char *assembly_name = class_name + strlen (class_name) + 1;
10072 return mono_get_exception_missing_method (class_name, assembly_name);
10074 case MONO_EXCEPTION_MISSING_FIELD: {
10075 char *class_name = (char *)exception_data;
10076 char *member_name = class_name + strlen (class_name) + 1;
10078 return mono_get_exception_missing_field (class_name, member_name);
10080 case MONO_EXCEPTION_FILE_NOT_FOUND: {
10081 char *msg_format = (char *)exception_data;
10082 char *assembly_name = msg_format + strlen (msg_format) + 1;
10083 char *msg = g_strdup_printf (msg_format, assembly_name);
10086 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
10092 case MONO_EXCEPTION_BAD_IMAGE: {
10093 return mono_get_exception_bad_image_format ((const char *)exception_data);
10096 MonoLoaderError *error;
10099 error = mono_loader_get_last_error ();
10100 if (error != NULL){
10101 ex = mono_loader_error_prepare_exception (error);
10105 /* TODO - handle other class related failures */
10112 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
10114 outer_klass = mono_class_get_generic_type_definition (outer_klass);
10115 inner_klass = mono_class_get_generic_type_definition (inner_klass);
10117 if (outer_klass == inner_klass)
10119 inner_klass = inner_klass->nested_in;
10120 } while (inner_klass);
10125 mono_class_get_generic_type_definition (MonoClass *klass)
10127 return klass->generic_class ? klass->generic_class->container_class : klass;
10131 * Check if @klass is a subtype of @parent ignoring generic instantiations.
10133 * Generic instantiations are ignored for all super types of @klass.
10135 * Visibility checks ignoring generic instantiations.
10138 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
10141 klass = mono_class_get_generic_type_definition (klass);
10142 parent = mono_class_get_generic_type_definition (parent);
10143 mono_class_setup_supertypes (klass);
10145 for (i = 0; i < klass->idepth; ++i) {
10146 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
10152 * Subtype can only access parent members with family protection if the site object
10153 * is subclass of Subtype. For example:
10154 * class A { protected int x; }
10156 * void valid_access () {
10160 * void invalid_access () {
10167 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
10169 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
10172 if (context_klass == NULL)
10174 /*if access_klass is not member_klass context_klass must be type compat*/
10175 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10181 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10184 if (accessing == accessed)
10186 if (!accessed || !accessing)
10189 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10190 * anywhere so untrusted friends are not safe to access platform's code internals */
10191 if (mono_security_core_clr_enabled ()) {
10192 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10196 mono_assembly_load_friends (accessed);
10197 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10198 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10199 /* Be conservative with checks */
10200 if (!friend_->name)
10202 if (strcmp (accessing->aname.name, friend_->name))
10204 if (friend_->public_key_token [0]) {
10205 if (!accessing->aname.public_key_token [0])
10207 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10216 * If klass is a generic type or if it is derived from a generic type, return the
10217 * MonoClass of the generic definition
10218 * Returns NULL if not found
10221 get_generic_definition_class (MonoClass *klass)
10224 if (klass->generic_class && klass->generic_class->container_class)
10225 return klass->generic_class->container_class;
10226 klass = klass->parent;
10232 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10235 for (i = 0; i < ginst->type_argc; ++i) {
10236 MonoType *type = ginst->type_argv[i];
10237 switch (type->type) {
10238 case MONO_TYPE_SZARRAY:
10239 if (!can_access_type (access_klass, type->data.klass))
10242 case MONO_TYPE_ARRAY:
10243 if (!can_access_type (access_klass, type->data.array->eklass))
10246 case MONO_TYPE_PTR:
10247 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10250 case MONO_TYPE_CLASS:
10251 case MONO_TYPE_VALUETYPE:
10252 case MONO_TYPE_GENERICINST:
10253 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10263 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10267 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10270 if (access_klass->element_class && !access_klass->enumtype)
10271 access_klass = access_klass->element_class;
10273 if (member_klass->element_class && !member_klass->enumtype)
10274 member_klass = member_klass->element_class;
10276 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10278 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10281 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
10284 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10287 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10290 /*Non nested type with nested visibility. We just fail it.*/
10291 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10294 switch (access_level) {
10295 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10296 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10298 case TYPE_ATTRIBUTE_PUBLIC:
10301 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10304 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10305 return is_nesting_type (member_klass, access_klass);
10307 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10308 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10310 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10311 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10313 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10314 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10315 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10317 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10318 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10319 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10324 /* FIXME: check visibility of type, too */
10326 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10328 MonoClass *member_generic_def;
10329 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10332 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
10333 access_klass->generic_container) &&
10334 (member_generic_def = get_generic_definition_class (member_klass))) {
10335 MonoClass *access_container;
10337 if (access_klass->generic_container)
10338 access_container = access_klass;
10340 access_container = access_klass->generic_class->container_class;
10342 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10346 /* Partition I 8.5.3.2 */
10347 /* the access level values are the same for fields and methods */
10348 switch (access_level) {
10349 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10350 /* same compilation unit */
10351 return access_klass->image == member_klass->image;
10352 case FIELD_ATTRIBUTE_PRIVATE:
10353 return access_klass == member_klass;
10354 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10355 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10356 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10359 case FIELD_ATTRIBUTE_ASSEMBLY:
10360 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10361 case FIELD_ATTRIBUTE_FAMILY:
10362 if (is_valid_family_access (access_klass, member_klass, context_klass))
10365 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10366 if (is_valid_family_access (access_klass, member_klass, context_klass))
10368 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10369 case FIELD_ATTRIBUTE_PUBLIC:
10376 * mono_method_can_access_field:
10377 * @method: Method that will attempt to access the field
10378 * @field: the field to access
10380 * Used to determine if a method is allowed to access the specified field.
10382 * Returns: TRUE if the given @method is allowed to access the @field while following
10383 * the accessibility rules of the CLI.
10386 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10388 /* FIXME: check all overlapping fields */
10389 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10391 MonoClass *nested = method->klass->nested_in;
10393 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10396 nested = nested->nested_in;
10403 * mono_method_can_access_method:
10404 * @method: Method that will attempt to access the other method
10405 * @called: the method that we want to probe for accessibility.
10407 * Used to determine if the @method is allowed to access the specified @called method.
10409 * Returns: TRUE if the given @method is allowed to invoke the @called while following
10410 * the accessibility rules of the CLI.
10413 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10415 int can = can_access_member (method->klass, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10417 MonoClass *nested = method->klass->nested_in;
10419 can = can_access_member (nested, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10422 nested = nested->nested_in;
10427 * with generics calls to explicit interface implementations can be expressed
10428 * directly: the method is private, but we must allow it. This may be opening
10429 * a hole or the generics code should handle this differently.
10430 * Maybe just ensure the interface type is public.
10432 if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
10438 * mono_method_can_access_method_full:
10439 * @method: The caller method
10440 * @called: The called method
10441 * @context_klass: The static type on stack of the owner @called object used
10443 * This function must be used with instance calls, as they have more strict family accessibility.
10444 * It can be used with static methods, but context_klass should be NULL.
10446 * Returns: TRUE if caller have proper visibility and acessibility to @called
10449 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10451 MonoClass *access_class = method->klass;
10452 MonoClass *member_class = called->klass;
10453 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10455 MonoClass *nested = access_class->nested_in;
10457 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10460 nested = nested->nested_in;
10467 can = can_access_type (access_class, member_class);
10469 MonoClass *nested = access_class->nested_in;
10471 can = can_access_type (nested, member_class);
10474 nested = nested->nested_in;
10481 if (called->is_inflated) {
10482 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10483 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10492 * mono_method_can_access_field_full:
10493 * @method: The caller method
10494 * @field: The accessed field
10495 * @context_klass: The static type on stack of the owner @field object used
10497 * This function must be used with instance fields, as they have more strict family accessibility.
10498 * It can be used with static fields, but context_klass should be NULL.
10500 * Returns: TRUE if caller have proper visibility and acessibility to @field
10503 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10505 MonoClass *access_class = method->klass;
10506 MonoClass *member_class = field->parent;
10507 /* FIXME: check all overlapping fields */
10508 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10510 MonoClass *nested = access_class->nested_in;
10512 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10515 nested = nested->nested_in;
10522 can = can_access_type (access_class, member_class);
10524 MonoClass *nested = access_class->nested_in;
10526 can = can_access_type (nested, member_class);
10529 nested = nested->nested_in;
10539 * mono_class_can_access_class:
10540 * @source_class: The source class
10541 * @target_class: The accessed class
10543 * This function returns is @target_class is visible to @source_class
10545 * Returns: TRUE if source have proper visibility and acessibility to target
10548 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10550 return can_access_type (source_class, target_class);
10554 * mono_type_is_valid_enum_basetype:
10555 * @type: The MonoType to check
10557 * Returns: TRUE if the type can be used as the basetype of an enum
10559 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10560 switch (type->type) {
10563 case MONO_TYPE_BOOLEAN:
10566 case MONO_TYPE_CHAR:
10580 * mono_class_is_valid_enum:
10581 * @klass: An enum class to be validated
10583 * This method verify the required properties an enum should have.
10585 * Returns: TRUE if the informed enum class is valid
10587 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10588 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10589 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10591 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10592 MonoClassField * field;
10593 gpointer iter = NULL;
10594 gboolean found_base_field = FALSE;
10596 g_assert (klass->enumtype);
10597 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10598 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10602 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10605 while ((field = mono_class_get_fields (klass, &iter))) {
10606 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10607 if (found_base_field)
10609 found_base_field = TRUE;
10610 if (!mono_type_is_valid_enum_basetype (field->type))
10615 if (!found_base_field)
10618 if (klass->method.count > 0)
10625 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10627 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10631 * mono_class_setup_interface_id:
10633 * Initializes MonoClass::interface_id if required.
10635 * LOCKING: Acquires the loader lock.
10638 mono_class_setup_interface_id (MonoClass *klass)
10640 mono_loader_lock ();
10641 if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10642 klass->interface_id = mono_get_unique_iid (klass);
10643 mono_loader_unlock ();
10647 * mono_class_alloc_ext:
10649 * Allocate klass->ext if not already done.
10652 mono_class_alloc_ext (MonoClass *klass)
10659 ext = (MonoClassExt *)mono_class_alloc0 (klass, sizeof (MonoClassExt));
10660 mono_image_lock (klass->image);
10661 mono_memory_barrier ();
10664 class_ext_size += sizeof (MonoClassExt);
10665 mono_image_unlock (klass->image);
10669 * mono_class_setup_interfaces:
10671 * Initialize klass->interfaces/interfaces_count.
10672 * LOCKING: Acquires the loader lock.
10673 * This function can fail the type.
10676 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10678 int i, interface_count;
10679 MonoClass **interfaces;
10681 mono_error_init (error);
10683 if (klass->interfaces_inited)
10686 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10687 MonoType *args [1];
10689 /* generic IList, ICollection, IEnumerable */
10690 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10691 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10693 args [0] = &klass->element_class->byval_arg;
10694 interfaces [0] = mono_class_bind_generic_parameters (
10695 mono_defaults.generic_ilist_class, 1, args, FALSE);
10696 if (interface_count > 1)
10697 interfaces [1] = mono_class_bind_generic_parameters (
10698 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10699 } else if (klass->generic_class) {
10700 MonoClass *gklass = klass->generic_class->container_class;
10702 mono_class_setup_interfaces (gklass, error);
10703 if (!mono_error_ok (error)) {
10704 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10708 interface_count = gklass->interface_count;
10709 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10710 for (i = 0; i < interface_count; i++) {
10711 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10712 if (!mono_error_ok (error)) {
10713 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10718 interface_count = 0;
10722 mono_image_lock (klass->image);
10724 if (!klass->interfaces_inited) {
10725 klass->interface_count = interface_count;
10726 klass->interfaces = interfaces;
10728 mono_memory_barrier ();
10730 klass->interfaces_inited = TRUE;
10733 mono_image_unlock (klass->image);
10737 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10739 MonoClass *klass = field->parent;
10740 MonoImage *image = klass->image;
10741 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10742 int field_idx = field - klass->fields;
10744 mono_error_init (error);
10747 MonoClassField *gfield = >d->fields [field_idx];
10748 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10749 if (!mono_error_ok (error)) {
10750 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10751 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10754 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10755 if (!mono_error_ok (error)) {
10756 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10757 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10761 guint32 cols [MONO_FIELD_SIZE];
10762 MonoGenericContainer *container = NULL;
10763 int idx = klass->field.first + field_idx;
10765 /*FIXME, in theory we do not lazy load SRE fields*/
10766 g_assert (!image_is_dynamic (image));
10768 if (klass->generic_container) {
10769 container = klass->generic_container;
10771 container = gtd->generic_container;
10772 g_assert (container);
10775 /* klass->field.first and idx points into the fieldptr table */
10776 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10778 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10779 mono_error_set_type_load_class (error, klass, "Could not verify field %s signature", field->name);;
10780 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
10784 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10786 mono_metadata_decode_value (sig, &sig);
10787 /* FIELD signature == 0x06 */
10788 g_assert (*sig == 0x06);
10790 field->type = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10791 if (!field->type) {
10792 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10793 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10799 mono_field_resolve_flags (MonoClassField *field)
10801 MonoClass *klass = field->parent;
10802 MonoImage *image = klass->image;
10803 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10804 int field_idx = field - klass->fields;
10808 MonoClassField *gfield = >d->fields [field_idx];
10809 return mono_field_get_flags (gfield);
10811 int idx = klass->field.first + field_idx;
10813 /*FIXME, in theory we do not lazy load SRE fields*/
10814 g_assert (!image_is_dynamic (image));
10816 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10821 * mono_class_setup_basic_field_info:
10822 * @class: The class to initialize
10824 * Initializes the klass->fields array of fields.
10825 * Aquires the loader lock.
10828 mono_class_setup_basic_field_info_locking (MonoClass *klass)
10830 mono_loader_lock ();
10831 mono_class_setup_basic_field_info (klass);
10832 mono_loader_unlock ();
10836 * mono_class_get_fields_lazy:
10837 * @klass: the MonoClass to act on
10839 * This routine is an iterator routine for retrieving the fields in a class.
10840 * Only minimal information about fields are loaded. Accessors must be used
10841 * for all MonoClassField returned.
10843 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10844 * iterate over all of the elements. When no more values are
10845 * available, the return value is NULL.
10847 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10850 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10852 MonoClassField* field;
10856 mono_class_setup_basic_field_info_locking (klass);
10857 if (!klass->fields)
10859 /* start from the first */
10860 if (klass->field.count) {
10861 *iter = &klass->fields [0];
10862 return (MonoClassField *)*iter;
10868 field = (MonoClassField *)*iter;
10870 if (field < &klass->fields [klass->field.count]) {
10872 return (MonoClassField *)*iter;
10878 mono_class_full_name (MonoClass *klass)
10880 return mono_type_full_name (&klass->byval_arg);
10883 /* Declare all shared lazy type lookup functions */
10884 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, System.Runtime.InteropServices, SafeHandle)